在单个调用中从Excel中检索多个单元格属性

本文关键字:单元格 属性 检索 Excel 单个 调用 | 更新日期: 2023-09-27 18:05:01

我需要检索几千个单元格的背景属性(Range.Interior.Color)。由于COM-Interop的限制,单独遍历每个单元非常慢。

是否有可能检索细胞属性,不是.Text, .Value.Value2Range包含一个以上的细胞在一个单独的调用?

在单个调用中从Excel中检索多个单元格属性

我会尝试以下(在VBA中编写,但可以转换为c#):

Public Sub GetColors()
    Dim ewsTarget As Worksheet: Set ewsTarget = ActiveWorkbook.Worksheets(1)
    ewsTarget.Copy , ewsTarget.Parent.Worksheets(ewsTarget.Parent.Worksheets.Count)
    Dim ewsCopy As Worksheet: Set ewsCopy = ewsTarget.Parent.Worksheets(ewsTarget.Parent.Worksheets.Count)
    ewsCopy.UsedRange.ClearContents
    ewsCopy.UsedRange.Columns.EntireColumn.ColumnWidth = 0.5
    ewsCopy.UsedRange.Rows.EntireRow.RowHeight = 5#
    ewsCopy.UsedRange.CopyPicture xlScreen, xlBitmap
    ewsCopy.Delete
End Sub

这段代码在剪贴板上放置了一个位图。此位图是从工作表的副本创建的,但是,单元格内容被删除,因此您将只看到单元格的背景,而且行和列具有相同的高度和长度。然后你的c#程序可以获取这个位图,并考虑到单元格的位置可以很容易地计算出来,因为行和列具有相同的高度和宽度。

我知道这只是一个权宜之计,但我不认为有更好的解决方案。它是单向的(不能写,只能读),并且很难扩展到其他属性(可能是边框和字体颜色)。

您可以这样做,但这不是微不足道的,所以我不确定是否值得尝试模仿类似的行为。

基本上你需要在Excel中创建一个宏来为你做这项工作,然后在宏完成后简单地把结果带回来。这基本上模拟了Value的行为。我真的不确定为什么微软决定不实现Range中的所有属性以相同的方式表现,奇怪。

为了做到这一点,你需要引用Microsoft Visual Basic for Application Extensibility 5.3 COM库。这为您提供了动态构建宏并将宏添加到Excel工作簿所需的工具。

第一步是创建一个方法,该方法将模块和所需的宏添加到您正在与之交互的工作簿(如果您正在打开和关闭的不同工作簿上使用该函数,您也可以打开一个空白工作簿并在那里创建宏)。

下面的示例添加了一个宏,该宏返回具有指定范围内所有单元格颜色的数组。这是用VBA写的,我没有VS,但c#版本应该很容易移植。

Sub AddCode()
   Dim wb As Workbook
   Dim xPro As VBIDE.VBProject
   Dim xCom As VBIDE.VBComponent
   Dim xMod As VBIDE.CodeModule
   Set wb = ActiveWorkbook
   With wb
       Set xPro = .VBProject
       Set xCom = xPro.VBComponents.Add(vbext_ct_StdModule)
       Set xMod = xCom.CodeModule
       With xMod
           .AddFromString "Public Function GetInteriorColors(r As Range) As Variant" & vbCrLf & _
                          "    Dim colors() As Long" & vbCrLf & _
                          "    Dim row As Integer" & vbCrLf & _
                          "    Dim column As Integer" & vbCrLf & _
                          "    ReDim colors(r.Rows.Count - 1, r.Columns.Count - 1)" & vbCrLf & _
                          "    For row = 1 To r.Rows.Count" & vbCrLf & _
                          "        For column = 1 To r.Columns.Count" & vbCrLf & _
                          "            colors(row - 1, column - 1) = r.Cells(row, column).Interior.Color" & vbCrLf & _
                          "        Next" & vbCrLf & _
                          "    Next" & vbCrLf & _
                          "    GetInteriorColors = colors" & vbCrLf & _
                          "End Function"
       End With
   End With
End Sub

值得注意的事情;我有时得到一个奇怪的错误时,执行AddFromString。宏代码被正确地添加到模块,但我有时会得到一个错误;吞咽它似乎没有什么害处,但如果你有同样的问题,我会调查一下。

现在,一旦你有了宏,恢复结果很容易(同样,用VBA编写):

Public Function GetColors(r As Range) As Long()
    //Note the absolute path to the macro; this is probably needed if the macro is in a different workbook.
    GetColors = Application.Run(ActiveWorkbook.Name & "!GetInteriorColors", r)
End Function