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

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

是否有可能从单个调用中包含多个单元格的Range中检索不是.Text.Value.Value2单元格属性?

你可以做到这一点,但它不是微不足道的,所以我不太确定它是否值得尝试模仿类似行为的麻烦。

基本上你需要在Excel中创build一个macros来为你完成工作,然后在macros完成后简单地返回结果。 这基本上模仿了Value的行为。 我不确定为什么MS决定不执行Range内的所有属性来performance相同的方式,更奇怪。

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

第一步是创build一个方法,将模块和所需的macros添加到正在与之交互的工作簿(如果要在打开和closures的不同工作表上使用该函数,还可以打开空白工作簿并在其中创buildmacros)。

以下示例添加一个macros,该macros返回指定范围内所有单元格颜色的数组。 这是写在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时,我有时会遇到一个奇怪的错误。 macros代码被正确添加到模块,但我有时会得到一个错误; 吞咽它似乎不是有害的,但如果你有同样的问题,我会研究它。

现在,一旦你有macros,带来的结果很容易(再次,写在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 

我会尝试以下(用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 

这段代码在剪贴板上放置一个位图。 此位图是从工作表的副本创build的,但是,单元格内容将被删除,因此您将只能看到单元格的背景,而且行和列的高度和长度相同。 您的C#程序可以获取这个位图,并获得单个像素,因为行和列具有相同的高度和宽度,因此可以轻松地计算单元格的位置。

我知道这只是一个解决方法,但我不认为有更好的解决scheme。 这是一种方式(不能写,只能读),很难扩展到其他属性(可能是边框和字体颜色)。