Резюме
Этот вопрос является продолжением этого вопроса:
Как реализовать самоназначение столбца из его индекса?
Протестировав код, приведенный в ответах на этот вопрос, приведенный выше, я наконец столкнулся с серьезной проблемой производительности.
Проблемы с производительностью
Проблема производительности возникает при инициализации листа, то есть когда я инициализирую ячейки листа.
''' <summary>
''' Initialize an instance of the Company.Project.Sheet class.
''' </summary>
''' <param name="nativeSheet">The native worksheet from which to initialize.</param>
Friend Sub New(ByVal nativeSheet As Microsoft.Office.Interop.Excel.Worksheet)
_nativeSheet = nativeSheet
Dim cells As IDictionary(Of String, ICell) = New Dictionary(Of String, ICell)()
'These iterations hurt the performance of the API...'
For rowIndex As Integer = 1 To _nativeSheet.Rows.Count Step 1
For colIndex As Integer = 1 To _nativeSheet.Columns.Count Step 1
Dim c As ICell = New Cell(_nativeSheet.Cells(rowIndex, colIndex))
cellules.Add(c.Name, c)
Next
Next
_cellules = New ReadOnlyDictionary(Of String, ICell)(cells)
End Sub
- ReadOnlyDictionary (Of TKey, TValue) :
A custom read-only dictionary that simply wraps a IDictionary(Of TKey, TValue) to prevent modifications.
Обсуждение
Я работаю таким образом, поскольку каждая ячейка в базовой электронной таблице инициализируется от инициализации рабочей таблицы до конца, то есть, когда рабочая таблица удаляется или завершается. Следовательно, таким же образом я хочу инициализировать ячейки листа, но я также хочу сохранить повышение производительности при использовании индексированных ячеек над именованными («A1») ячейками, сохраняя при этом простоту использования для пользователя API для обращайтесь к ячейке с ее именем, именно так я собираюсь использовать словарь, поэтому, когда я обращаюсь к ячейке «A1», я получаю доступ к этому ключу в своем словаре и адресую ячейку (1, 1) соответственно.
Кроме того, я знаю еще более быстрый способ чтения с рабочего листа с помощью свойства Worksheet.UsedRange, которое возвращает все использованные ячейки в 2D-матрицу.
Если бы в любом случае было то же самое или примерно одинаковое для набора ячеек, с которым я мог бы инициализировать несколько экземпляров своего класса Cell, это было бы здорово и эффективно!
Я также думал об инициализации, как только ячейки матрицы 100 × 100 в памяти, при сопоставлении их со своим словарем, так как редко будут использоваться ячейки всего листа. Таким образом, я все еще думаю о способе, которым я должен был бы получить доступ к еще не инициализированной ячейке, скажем, Клеткам (120, 120). В идеале, я думаю, программа должна была бы инициализировать все ячейки между максимально первоначально инициализированной ячейкой (100, 100) и до ячейки (120, 120). Я достаточно ясно здесь? Не стесняйтесь просить разъяснений! =)
Другой вариант может состоять в том, что я только инициализирую имена ячеек в словаре и сохраняю там индекс строки и столбца в памяти, а не инициализирую экземпляр Cell с его nativeCell, скажем Range. Вот код моего класса Cell, чтобы проиллюстрировать, что я имею в виду.
''»
'' 'Представляет ячейку на листе.
«»»
«»»
Друг класс ячейки
Реализует ICell
Private _nativeCell As Microsoft.Office.Interop.Excel.Range
Private _name As String
''' <summary>
''' Initializes a new instance of the Company.Project.Cell class.
''' </summary>
''' <param name="nativeCell">The Microsoft.Office.Interop.Excel.Range to wrap.</param>
Friend Sub New(ByVal nativeCell As Microsoft.Office.Interop.Excel.Range)
_nativeCell = nativeCell
End Sub
Public ReadOnly Property NativeCell() As Microsoft.Office.Interop.Excel.Range Implements ICellule.NativeCell
Get
Return _nativeCell
End Get
End Property
Public ReadOnly Property Column() As Integer Implements ICell.Column
Get
Return _nativeCell.Column
End Get
End Property
Public ReadOnly Property Row() As Integer Implements ICell.Row
Get
Return _nativeCell.Row
End Get
End Property
Public ReadOnly Property Name() As String Implements ICellule.Name
Get
If (String.IsNullOrEmpty(_name) OrElse _name.Trim().Length = 0) Then _
_name = GetColumnName()
Return _nom
End Get
End Property
Public Property Value() As Object Implements ICellule.Value
Get
Return _nativeCell.Value2
End Get
Set(ByVal value As Object)
_nativeCell.Value2 = value
End Set
End Property
Public ReadOnly Property FormattedValue() As String Implements ICellule.FormattedValue
Get
Return _nativeCell.Text
End Get
End Property
Public ReadOnly Property NumericValue() As Double? Implements ICellule.NumericValue
Get
Return Value
End Get
End Property
Вопросы
Какие у меня есть другие варианты?
Есть ли другие способы пройти?
Есть ли способ сделать реальный подход жизнеспособным с точки зрения производительности?
К вашему сведению, эта проблема устарела при тестировании, поэтому тестирование никогда не завершалось в течение приемлемого промежутка времени, который на самом деле занимает столетия ...
Любые мысли приветствуются! Я открыт для других решений или подходов, которые помогут мне достичь этой цели при решении проблемы с производительностью.
Спасибо вам всем! =) * * Тысяча восемьдесят-два
РЕДАКТИРОВАТЬ # 1
Благодаря Максиму Геевандову , его решение решает проблему, которую я затронул в этом вопросе.
Кроме этого, из этого решения возникла еще одна проблема: SystemOutOfMemoryException
, и она будет рассмотрена в другом вопросе.
Моя искренняя благодарность Максиму Геевандову.