我正在使用 Visual Studio 2010 中的 Excel 互操作来尝试按字母顺序对所有这些数据行进行排序。有些已经按字母顺序排列。
Accountancy Graduate, Trainees Banking, Insurance, Finance
Accountancy Graduate, Trainees Customer Services
Accountancy Graduate, Trainees Education
Accountancy Graduate, Trainees Health, Nursing
Accountancy Graduate, Trainees Legal
Accountancy Graduate, Trainees Management Consultancy
Accountancy Graduate, Trainees Media, New Media, Creative
Accountancy Graduate, Trainees Oil, Gas, Alternative Energy
Accountancy Graduate, Trainees Public Sector & Services
Accountancy Graduate, Trainees Recruitment Sales
Accountancy Graduate, Trainees Secretarial, PAs, Administration
Accountancy Graduate, Trainees Telecommunications
Accountancy Graduate, Trainees Transport, Logistics
我的代码的当前版本如下(我让我的代码在将其放入 fs 文件之前以交互方式工作)。
#r "office.dll"
#r "Microsoft.Office.Interop.Excel.dll"
open System;;
open System.IO;;
open Microsoft.Office.Interop.Excel;;
let app = new ApplicationClass(Visible = true)
let inputBook = app.Workbooks.Open @"C:\Users\simon.hayward\Dropbox\F# Scripts\TotalJobsSort\SortData.xlsx" //work
//let inputBook = app.Workbooks.Open @"C:\Users\Simon Hayward\Dropbox\F# Scripts\TotalJobsSort\SortData.xlsx" //home
let outputBook = app.Workbooks.Add()
let inSheet = inputBook.Worksheets.[1] :?> _Worksheet
let outSheet = outputBook.Worksheets.[1] :?> _Worksheet
let rows = inSheet.UsedRange.Rows.Count;;
let toSeq (range : Range) =
seq {
for r in 1 .. range.Rows.Count do
for c in 1 .. range.Columns.Count do
let cell = range.Item(r, c) :?> Range
yield cell
}
for i in 1 .. rows do
let mutable row = inSheet.Cells.Rows.[i] :?> Range
row |> toSeq |> Seq.map (fun x -> x.Value2.ToString()) |> Seq.sort |>
(outSheet.Cells.Rows.[i] :?> Range).Value2 <- row.Value2;;
app.Quit();;
但是类型有问题。退出命令前的最后一行
(outSheet.Cells.Rows.[i] :?> Range).Value2 <- row.Value2;;
智能感知用红色下划线,我得到的错误是
“这个表达式应该有类型 seq -> 'a 但这里有类型 unit”。
我得到了 VS 试图告诉我的内容,但我现在已经多次尝试解决这个问题,但我似乎无法解决类型问题。
谁能告诉我如何将管道设置为正确的类型,以便输出写入我的输出表?
编辑 1:这是我得到的完整错误消息,其中 sorted 变量注释如下
let sorted = row |> toSeq //|> Seq.map (fun x -> x.Value2.ToString()) |> Seq.sort
错误信息是:-
System.Runtime.InteropServices.COMException (0x800A03EC):来自 HRESULT 的异常:System.RuntimeType.ForwardCallToInvokeMember 的 0x800A03EC(String memberName, BindingFlags flags, Object target, Int32[] aWrapperTypes, MessageData& msgData) at Microsoft.Office.Interop.Excel.Range .get_Item(Object RowIndex, Object ColumnIndex) at FSI_0122.toSeq@34-47.Invoke(Int32 c) in C:\Users\Simon Hayward\Dropbox\F# Scripts\TotalJobsSort\sortExcelScript.fsx:Microsoft.FSharp 的第 36 行。 Collections.IEnumerator.map@109.DoMoveNext(b& ) 在 Microsoft.FSharp.Collections.IEnumerator.MapEnumerator
1.System-Collections-IEnumerator-MoveNext() at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeOuter@651[T,TResult](ConcatEnumerator
2 x,单位 unitVar0) 在 Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeInner@644[T,TResult](ConcatEnumerator2 x, Unit unitVar0) at <StartupCode$FSharp-Core>.$Seq.MoveNextImpl@751.GenerateNext(IEnumerable
1&下一个)在 Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase1.MoveNextImpl() at Microsoft.FSharp.Core.CompilerServices.GeneratedSequenceBase
1.System-Collections-IEnumerator-MoveNext() at Microsoft.FSharp.Collections.SeqModule.ToArray[T](IEnumerable1 source) at Microsoft.FSharp.Collections.ArrayModule.OfSeq[T](IEnumerable
1 source) at .$FSI_0122.main@() in C:\Users\Simon Hayward\Dropbox\F# Scripts\TotalJobsSort\sortExcelScript.fsx:line 42 由于错误而停止
编辑 2:这个问题可能是由于 toSeq 函数被设计为将整个工作表变成一个序列吗?在我应用它的地方,我只希望它适用于一行。
我尝试将 toSeq 中的 r 变量限制为 1,但这没有帮助。
我的实际数据是锯齿状数组这一事实是否重要?它并不总是每行有 3 个条目,它在 1 到 4 之间变化。
编辑 3:
这是我的代码的当前迭代,基于 Tomas 的建议
#r "office.dll"
#r "Microsoft.Office.Interop.Excel.dll"
open System;;
open System.IO;;
open Microsoft.Office.Interop.Excel;;
let app = new ApplicationClass(Visible = true);;
let inputBook = app.Workbooks.Open @"SortData.xlsx" //workbook
let outputBook = app.Workbooks.Add();;
let inSheet = inputBook.Worksheets.[1] :?> _Worksheet
let outSheet = outputBook.Worksheets.[1] :?> _Worksheet
let rows = inSheet.UsedRange.Rows.Count;;
let columns = inSheet.UsedRange.Columns.Count;;
// Get the row count and calculate the name of the last cell e.g. "A13"
let rangeEnd = sprintf "A%d" columns
// Get values in the range A1:A13 as 2D object array of size 13x1
let values = inSheet.Range("A1", rangeEnd).Value2 :?> obj[,]
// Read values from the first (and only) column into 1D string array
let data = [| for i in 1 .. columns -> values.[1, i] :?> string |]
// Sort the array and get a new sorted 1D array
let sorted1D = data |> Array.sort
// Turn the 1D array into 2D array (13x1), so that we can write it back
let sorted2D = Array2D.init 1 columns (fun i _ -> data.[i])
// Write the data to the output sheet in Excel
outSheet.Range("A1", rangeEnd).Value2 <- sorted2D
但是因为实际数据在每一行中都有可变数量的条目,所以我得到了标准范围异常错误(这至少是对过去几天的 HRESULT 异常错误的改进)。
所以我需要为每一行定义列,或者只是将行的长度绑定到 for 循环中的一个变量。(我猜)。