gpt4 book ai didi

.net - 在允许我实例化工作表的单元格的同时,使用什么架构来解决这个 SystemOutOfMemoryException?

转载 作者:行者123 更新时间:2023-12-04 13:07:07 24 4
gpt4 key购买 nike

Summary



这个问题是为了构建一个简单的电子表格 API,同时保持它对那些熟悉 Excel 的人的用户友好的愿望的后续。

综上所述,这个问题与以下两个有关:
1. How to implement column self-naming from its index? ;
2. How to make this custom worksheet initialization faster? .

Objective



提供一个简化的 Excel API,用作神经元组件的包装器,例如 Application , Workbook , WorksheetRange类/接口(interface),同时仅公开每个对象最常用的对象属性。

Usage example



这个使用示例的灵感来自单元测试,这些单元测试使我能够将此解决方案提升到现在的水平。
Dim file as String = "C:\Temp\WriteTest.xls"

Using mgr As ISpreadsheetManager = New SpreadsheetManager()
Dim wb as IWorkbook = mgr.CreateWorkbook()
wb.Sheets("Sheet1").Cells("A1").Value = 3.1415926
wb.SaveAs(file)
End Using

现在我们打开它:
Dim file as String = "C:\Temp\WriteTest.xls"

Using mgr As ISpreadsheetManager = New SpreadsheetManager()
Dim wb as IWorkbook = mgr.OpenWorkbook(file)
// Working with workbook here...
End Using

Discussion



实例化 Excel 工作簿时:
  • Worksheet 的一个实例在 Workbook.Sheets 集合中自动初始化;
  • 初始化时,工作表通过 Range 初始化其单元格。可以表示一个或多个单元格的对象。

  • 一旦工作表存在,这些单元格就可以立即访问其所有属性。

    我的愿望是重现这种行为,以便
  • Workbook 类构造函数使用 native 工作表初始化 Workbook.Sheets 集合属性;
  • Worksheet 类构造函数使用 native 单元格初始化 Worksheet.Cells 集合属性。

  • 我的问题来自 Worksheet 类构造函数,同时初始化 #2 所示的 Worksheet.Cells 集合属性。

    Thoughts



    在遇到上述这些问题之后,我希望找出另一种架构,让我能够:
  • 访问单元格的特定功能Range在需要的时候;
  • 通过我的 ICell 提供最常用的属性界面;
  • 可以访问所有 Range工作表的单元格从其初始化。

  • 同时记住访问 Range.Value属性是使用 Interop 与基础 Excel 应用程序实例的最快交互。

    所以,我想初始化我的 ReadonlyOnlyDictionary(Of String, ICell)不立即包装 Range 实例的单元格名称接口(interface),这样我就可以简单地生成行和列索引以及单元格的名称来索引我的字典,然后分配 Cell.NativeCell仅当想要访问或格式化特定单元格或单元格范围时才具有属性。

    这样,字典中的数据将使用从 Worksheet 中生成的列索引获得的单元格名称进行索引。类构造函数。然后,当一个人会这样做:
    Using mgr As ISpreadsheetManager = New SpreadsheetManager()
    Dim wb As IWorkbook = mgr.CreateWorkbook()
    wb.Sheet(1).Cells("A1").Value = 3.1415926 // #1:
    End Using

    #1:这将允许我使用我的 Cell 中的索引类将给定值写入特定单元格,这比直接使用它的名称对 Range 更快。 .

    Questions and Concerns



    此外,在使用 UsedRange.get_Value() 时或 Cells.get_Value() ,这将返回 Object(,) 数组。

    1. 那么我应该对使用Object(,) 感到满意吗?单元格的数组,而无法以某种方式对其进行格式化?

    2. 如何构建这些 Worksheet 和 Cell 类,以便在使用 Object(,) 时获得最佳性能数组,同时保持 Cell 实例可以表示或包装单个单元格 Range 的可能性?

    Thanks to any of you who takes the time to read my post and my sincerest thanks to those who answer.

    最佳答案

    使用的体系结构经过了我命名为 CellCollection 的对象类。 .这是它的作用:
    基于这些假设:

    1. Given that an Excel worksheet has 256 columns and 65536 lines;

    2. Given that 16,777,216 (256 * 65536) cells needed to be instantiated at a time;

    3. Given that the most common use of a worksheet takes less then 1,000 lines and less than 100 columns;

    4. Given that I needed it to be able to refer to the cells with their addresses ("A1"); and

    5. Given that it is benchmarked that accessing all the values at once and load them into a object[,] in memory as being the fastest way to work with an underlying Excel worksheet,*


    我考虑过不实例化任何单元格,让我的 CellCollection我的 IWorksheet 内的属性(property)接口(interface)初始化并在实例化时为空,现有工作簿除外。因此,在打开工作簿时,我验证了 NativeSheet.UsedRange为空或返回 null(在 Visual Basic 中为空),否则,我已经在内存中获得了使用过的“ native 单元”,因此只需将它们添加到我的内部 CellCollection字典,同时用它们各自的地址索引它们。
    最后, Lazy Initialization拯救设计模式! =)
    public class Sheet : ISheet {
    public Worksheet(Microsoft.Office.Interop.Excel.Worksheet nativeSheet) {
    NativeSheet = nativeSheet;
    Cells = new CellCollection(this);
    }

    public Microsoft.Office.Interop.Excel.Worksheet NativeSheet { get; private set; }

    public CellCollection Cells { get; private set; }
    }

    public sealed class CellCollection {
    private IDictionary<string, ICell> _cells;
    private ReadOnlyDictionary<string, ICell> _readonlyCells;

    public CellCollection(ISheet sheet) {
    _cells = new Dictionary<string, ICell>();
    _readonlyCells = new ReadonlyDictionary<string, ICell>(_cells);
    Sheet = sheet;
    }

    public readonly ReadOnlyDictionary<string, ICell> Cells(string addresses) {
    get {
    if (string.IsNullOrEmpty(addresses) || 0 = address.Trim().Length)
    throw new ArgumentNullException("addresses");

    if (!Regex.IsMatch(addresses, "(([A-Za-z]{1,2,3}[0-9]*)[:,]*)"))
    throw new FormatException("addresses");

    foreach(string address in addresses.Split(",") {
    Microsoft.Office.Interop.Excel.Range range = Sheet.NativeSheet.Range(address)

    foreach(Microsoft.Office.Interop.Excel.Range cell in range) {
    ICell c = null;
    if (!_cells.TryGetValue(cell.Address(false, false), c)) {
    c = new Cell(cell);
    _cells.Add(c.Name, c);
    }
    }
    }

    return _readonlyCells;
    }
    }

    public readonly ISheet Sheet { get; private set; }
    }
    显然,这是第一次尝试,到目前为止它工作得很好,具有超过可接受的性能。不过谦虚地说,我觉得它可以使用一些优化,虽然我现在会这样使用它,如果需要,以后再优化它。
    在写完这个集合之后,我能够达到预期的行为。现在,我将尝试实现一些 .NET 接口(interface)以使其可用于某些 IEnumerable , IEnumerable<T> , ICollection , ICollection<T>等,因此可以分别将其视为真正的 .NET 集合。
    随意评论并为此代码带来 build 性的替代方案和/或更改,以便它可能变得比现在更大。
    我希望这有一天能达到目的。
    谢谢阅读! =)

    关于.net - 在允许我实例化工作表的单元格的同时,使用什么架构来解决这个 SystemOutOfMemoryException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5183833/

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