我正在尝试将电子表格数据捕获到2D数组中。我正在使用VSTO。
int rc = 1048576;
int cc = 1638;
string[,] arr = new string[rc, cc];
最后一行抛出Out of Memory异常。我想显示消息告诉用户只能捕获'X'元素。
已检查MSDN,并且提到的行数限制为16,777,216。无数据表的列数限制。无法找到2D阵列的限制。
我的问题不在于为什么例外。我正在寻找的是如果您正在进行VSTO开发,并且必须捕获DataTable中的工作表以执行内存中连接等,您将需要这样做:
string[,] arr = new string[rc, cc];
Microsoft.Office.Interop.Excel.Range selection
arr = selection.Value as string[,];
然后将该数组中的数据复制到datatable。现在,用户应该选择的元素数量的理想限制是什么。因此,当选择超出此条件时,我可以设置rowcount / columncount lmits并显示消息。
答案 0 :(得分:16)
我们来算一算。您正在尝试分配具有1048576 * 1638 = 1717567488元素的2D字符串数组。 x64上字符串引用的大小是8个字节=>共1717567488 * 8 = 13740539904字节。这是关于 13 GB 的连续内存空间。 CLR的单个分配的最大大小为2GB,因此您将获得OutOfMemoryException,因为无法分配单个块。
请注意,即使所有字符串都长1-2个字符,这样的字符串数量除了引用之外还需要30GB的字符串值。除了OutOfMemoryException
你还期望得到什么呢?
答案 1 :(得分:0)
阿莱克斯, 你要求限制内存分配。 让我建议改变你的观点和 限制您的输入
除了您的问题之外,我建议您注意Range.Value
和Range.Value2
的区别:Range.Value包含用户输入,例如:像=SUM(A1:B10)
这样的公式,而Range.Value2包含该公式的结果,例如10
。
1.1仅使用用户选择的单元格
如上所述here使用Range userSelectedRange = Application.Selection;
1.2仅使用xl.worksheet中确实使用过的单元格
使用Worksheet.Cells.SpecialCells
属性
也许Worksheet.UsedRange
更好。
代码示例:
int lastUsedRowIndex = xlWorksheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell).Row;
int lastUsedColIndex = xlWorksheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell).Column;
string rangeString = string.Format("A0:{0}{1}", SomeIndexToExcelColConverterFunc(lastUsedColIndex), lastUsedRowIndex));
Xl.Range range = xlWorksheet.Range[rangeString];
object[,] objectMatrix = range.Value2 as object[,];
Marshal.ReleaseComObject(range);
// convert to string here if needed