快速的方法来获取Excel范围为C#中的文本或单元格格式的数组?

数组操作比VSTO中的范围操作快,所以目前我正在使用

object[,] RangeValues = wsh.get_Range("A1:" + lastCell.Address).Value2; 

效果相当不错。 可悲的是,我有一些不一致的数据。 有时候有0.45 ,有时候是0.45% ,当然以后我会看到它是0.0045代码。 可悲的是,从“商业”的angular度来看,这两个值都意味着0.45 。 我不能强制一致性,文件来自我没有任何权限的各种来源。 这是我需要处理的事情。

当然,方法是查看格式或显示文本,看看是否有%符号。 如果有的话,我只需要将值乘以100.可悲的是,如果我尝试:

 object[,] RangeValues = wsh.get_Range("A1:" + lastCell.Address).Text; 

我得到消息,不能将DBNull转换为object[,] 。 那么是否有任何方法可以让我一次加载文本或格式,而不需要在mu循环的每个步骤都完成代码< – >工作表边界?

检测Excel单元格格式

要查找单元格的格式,请使用Excel的Cell("format",A1)函数,而不是询问数据types,这样会更慢,更困难,更容易出现问题,例如: 0.45%!= 45%

在这里输入图像说明

 private void button1_Click(object sender, EventArgs e) { // evaluate the Format of Cells A1 thru to A7 using (var rnEvaluate = xlApp.Range["C1:C1"].WithComCleanup()) { for (int i = 1; i < 8; i++) { rnEvaluate.Resource.Value2 = "=CELL(\"format\",A" + i.ToString() + ")"; string cellFormat = GetExcelCellFormat(rnEvaluate.Resource.Value2); System.Diagnostics.Debug.Write(cellFormat); } } } private string GetExcelCellFormat(string cellFormat = "G") { switch (cellFormat.Substring(0, 1)) { case "F" : return "Number"; break; case "P" : return "Percentage"; break; case "C": return "Currency"; break; case "D": return "Date"; break; default : return "General"; break; } } 

.WithComCleanup()是因为我正在使用VSTO Contrib 。


一次检测所有Excel单元格格式

有什么方法可以让我一次加载文本或格式?

只需使用上面的方法来检测所有的单元格格式(使用自动填充)并将它们添加到一个objectArray。 举例来说,我想知道列A和B的单元格格式:

在这里输入图像说明

使用这个VBA代码,我可以得到所有的单元格格式(一次不需要迭代单元格):

 Range("C1").Select ActiveCell.Value2 = "=CELL(""format"",A1)" 'Fill Down Range("C1").Select Selection.AutoFill Destination:=Range("C1:C6"), Type:=xlFillDefault 'Fill Across Range("C1:C6").Select Selection.AutoFill Destination:=Range("C1:D6"), Type:=xlFillDefault 

这里是上面的VBA代码转换为C#并将格式存储在对象数组中:

 var filepath = @"C:\temp\test\book2.xlsx"; var xlApp = new Microsoft.Office.Interop.Excel.Application(); //Optional but recommended if the user shouldn't see Excel. xlApp.Visible = false; xlApp.ScreenUpdating = false; //AddToMru parameter is optional, but recommended in automation scenarios. var workbook = xlApp.Workbooks.Open(filepath, AddToMru: false); //This operation may take a little bit of time but no where near 15 minutes!!! var cell = xlApp.Range["C1:C1"]; cell.Value2 = "=CELL(\"format\",A1)"; //Fill Down cell.AutoFill(xlApp.Range["C1:C6"], Microsoft.Office.Interop.Excel.XlAutoFillType.xlFillDefault); //Fill Across cell = xlApp.Range["C1:C6"]; cell.AutoFill(xlApp.Range["C1:D6"], Microsoft.Office.Interop.Excel.XlAutoFillType.xlFillDefault); //Get cell formats into object array object[,] rangeFormats = xlApp.get_Range("C1:D6").Value2; 

Excel百分比转换技巧

我有一些不一致的数据。 有时候有0.45,有时候是0.45%

如果您遇到的唯一数据不一致是值,那么这里就是一个窍门。

据推测,百分比值将在一列,转换它们,复制值的列(在列A):

在这里输入图像说明

确保你设置了一个值为100的列(如B列所示)

右键单击100列中的单元格并selectselect性粘贴:

在这里输入图像说明

select值并相乘:

在这里输入图像说明

Excel会将它们转换为实数:

在这里输入图像说明

显然,你可以通过编程来完成。 只需将操作logging为macros并将VBA转换为C#即可。

当然后来我在代码中看到它是0.0045。

注意:代码是正确的,0.45%不是45%,0.45%不到半个百分点! 如果一个特定的客户向你发送文件,希望你打破math规律,并把0.45%= 45%,那么他们很有可能突然开始获得100倍以上或100倍的收益。 我礼貌地指出他们需要改变它。 不要尝试和编程。 如果这就是为什么你想看单元格格式,那么你所做的只是解决症状,而不是修复会加剧问题的根本原因,并隐藏更大的问题。 只是礼貌地指出, 你无法控制的来源可能会有一些大的问题x100折叠,并坚持需要纠正。 否则,我期望在DailyWTF中看到一个有趣的故事:

 var val = rangeValues[1,1].ToString(); var cellFormat = rangeFormat[1,1].ToString(); if (val.EndsWith("%") && val.Replace("%","") < 1 && cellFormat == "G") { dailyWTFval = val.Replace("%","") * 100; } else dailyWTFval = val; } 

我认为从excel中读取大量非协调数据的最简单方法如下

  1. 在C#中保存XML Spreadsheet 2003(* xml)中的excel文件。 这将产生所有数据和样式的XML文件。 用于保存的C#方法 – 带有FileFormat的Workbook.SaveAs value = XlFileFormat.xlXMLSpreadsheet

  2. parsingXML文件并使用格式提取数据

  3. 删除临时文件

例子:Excel 高强

XML

 <?xml version="1.0"?> <?mso-application progid="Excel.Sheet"?> <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40"> <Styles> <Style ss:ID="Default" ss:Name="Normal"> <Alignment ss:Vertical="Bottom"/> <Borders/> <Font ss:FontName="Calibri" x:CharSet="204" x:Family="Swiss" ss:Size="11" ss:Color="#000000"/> <Interior/> <NumberFormat/> <Protection/> </Style> <Style ss:ID="s62"> <NumberFormat ss:Format="0%"/> </Style> </Styles> <Worksheet ss:Name="Sheet1"> <Table ss:ExpandedColumnCount="1" ss:ExpandedRowCount="5" x:FullColumns="1" x:FullRows="1" ss:DefaultRowHeight="15"> <Row ss:AutoFitHeight="0"> <Cell> <Data ss:Type="String">Data</Data> </Cell> </Row> <Row ss:AutoFitHeight="0"> <Cell> <Data ss:Type="Number">45</Data> </Cell> </Row> <Row ss:AutoFitHeight="0"> <Cell ss:StyleID="s62"> <Data ss:Type="Number">0.45</Data> </Cell> </Row> <Row ss:AutoFitHeight="0"> <Cell> <Data ss:Type="String">String</Data> </Cell> </Row> <Row ss:AutoFitHeight="0"> <Cell> <Data ss:Type="Number">45.5</Data> </Cell> </Row> </Table> </Worksheet> 

为了简单,我删除了一些节点。 以下元素需要进行分析才能正确提取数据

  1. Workbook \ Worksheet \ Table \ Row \ Cell \ Data – 包含形成不变文化的数据
  2. Workbook \ Worksheet \ Table \ Row \ Cell \ Data,属性ss:types – 包含数据元素内容的数据types
  3. Workbook \ Worksheet \ Table \ Row \ Cell,属性ss:StyleID – 对样式的引用,对于您的情况,只需要正确标识以百分比forms编号的单元格(需要乘以100)
  4. Workbook \ Styles \ Style,属性ss:ID – 用于从单元格引用样式的样式的ID
  5. Workbook \ Styles \ Style \ NumberFormat,attrubute ss:Format – 如果以%和数据types结尾Number – >它是百分比

parsing器逻辑:

  1. 单元格中的stringtypes – >按原样转换
  2. 单元格中的数字types。 如果格式以'%'结尾 – >乘以100,否则按原样使用。

如果数据量不是很大(小于200-300),则可以从C#中逐个单元格进行分析,而不用以xml格式保存文件。

这可能是一个糟糕的方式来做到这一点,但考虑重写你的Excel文件到一个新的Excel文件,转换为文本格式的过程中。 我build议这只是因为你可能没有原始文件的写权限,根据你的问题的意见。 查看如何转换整个文件(不包括新文件创build)的示例: https : //stackoverflow.com/a/25162945/5090027

另外,MSDN讨论了使用Spire [披露 – 我自己没有使用过]将整个文件导出为文本文件的方法: https : //code.msdn.microsoft.com/windowsdesktop/Export-Excel-Data-到文本015bc013