gpt4 book ai didi

excel - 在 F# (Office.Interop) 中按字母顺序对 Excel 行进行排序

转载 作者:行者123 更新时间:2023-12-03 02:09:46 26 4
gpt4 key购买 nike

我正在使用 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:这是我收到的完整错误消息,其中已排序的变量被注释掉,如下

let sorted = row |> toSeq //|> Seq.map (fun x -> x.Value2.ToString()) |> Seq.sort

错误消息是:-

System.Runtime.InteropServices.COMException (0x800A03EC): Exception from HRESULT: 0x800A03EC at System.RuntimeType.ForwardCallToInvokeMember(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:line 36 at Microsoft.FSharp.Collections.IEnumerator.map@109.DoMoveNext(b& ) at Microsoft.FSharp.Collections.IEnumerator.MapEnumerator1.System-Collections-IEnumerator-MoveNext()
at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeOuter@651[T,TResult](ConcatEnumerator
2 x, Unit unitVar0) at Microsoft.FSharp.Core.CompilerServices.RuntimeHelpers.takeInner@644[T,TResult](ConcatEnumerator2 x, Unit unitVar0)
at <StartupCode$FSharp-Core>.$Seq.MoveNextImpl@751.GenerateNext(IEnumerable
1& next) at 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 Stopped due to error

编辑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 异常错误的改进)。

所以我需要为每个单独的行定义列,或者只是将行的长度绑定(bind)到 for 循环中的变量。 (我猜)。

最佳答案

看起来您在 Seq.sort 行的末尾有一个额外的 |> 运算符 - 这意味着列表已排序,然后编译器尝试将其传递给执行赋值的表达式(该表达式不带任何参数并且类型为 unit)。

类似这样的东西应该可以编译(尽管可能存在一些其他运行时问题):

for i in 1 .. rows do 
let row = inSheet.Cells.Rows.[i] :?> Range
let sorted = row |> toSeq |> Seq.map (fun x -> x.Value2.ToString()) |> Seq.sort
(outSheet.Cells.Rows.[i] :?> Range).Value2 <- Array.ofSeq sorted

请注意,您不需要将 row 标记为可变,因为代码会创建一个副本(并且 - 在我的版本中 - 将其分配给新变量 sorted) .

我还使用 Array.ofSeq 将排序序列转换为数组,因为我认为 Excel 互操作对于数组效果更好。

在范围上设置 Value2 属性时,该范围的大小应与您分配给它的数组的大小相同。此外,根据您要设置的范围,您可能需要一个二维数组。

编辑关于运行时错误,我不完全确定您的代码出了什么问题,但这是我进行排序的方式(假设您只有一列包含字符串值并且您想要对行进行排序):

// Get the row count and calculate the name of the last cell e.g. "A13"
let rows = inSheet.UsedRange.Rows.Count
let rangeEnd = sprintf "A%d" rows

// 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 .. rows -> values.[i, 1] :?> 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 rows 1 (fun i _ -> data.[i])

// Write the data to the output sheet in Excel
outSheet.Range("A1", rangeEnd).Value2 <- sorted

关于excel - 在 F# (Office.Interop) 中按字母顺序对 Excel 行进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15223856/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com