Стремление найти лучший путь вперед. Мне нужно взять данные из двух отдельных книг Excel, состоящих из нескольких листов, и сохранить некоторые данные с каждого листа в зависимости от типа данных, чтобы я мог позже сравнить эти данные на каждом листе из каждой книги с другой.
Затем я создам еще одну рабочую тетрадь, чтобы обобщить результаты. Это выглядит так:
workbook1->sheetA->uniqueIdentifier->value associated with that identifier
workbook1->sheetB->uniqueIdentifier->value associated with that identifier
(и так далее для нескольких листов)
Такой же макет и для workbook2. Когда у меня есть данные со всех рабочих листов в каждой книге, я сравниваю данные. Макет листов одинаков в обеих книгах, а «uniqueIdentifier» уникален для этой книги, но также существует и в другой книге. В какой-то момент это вырастет до 3, затем 4, а затем 5 рабочих книг в будущем.
Это похоже на беспорядочный и неэффективный массив, поэтому я подумал, что, возможно, коллекция будет лучше. В любом случае, эту часть проекта кода я только начинаю, поэтому я надеялся получить некоторое представление, прежде чем спуститься в кроличью нору. Сейчас я опираюсь на коллекцию сборников......
Не уверен, что это подходит для stackoverflow? Больше похоже на вопрос дизайна. Но вот мои 2 цента.
Я работал над подобным случаем, и в моем случае всегда сравниваются рабочие книги, скажем, wbA
и wbB
, и в каждой из них есть один лист — sheetA
и sheetB
.
Мои пользователи должны ежемесячно сравнивать новые листы данных на основе одних и тех же конфигураций, поэтому я также прошу пользователя написать configuration json
и сообщить им, какую переменную они могут использовать в этом json.
Для ввода я прошу пользователя дать мне три файла — wbA's excel
, «wbB's excel» и configuration json
. Перетащите их из ОС и поместите в мою программу, а затем пусть моя программа обрабатывает их. Я также поддерживаю папки, чтобы пользователи могли легко классифицировать свои файлы.
Конфигурация json сообщает мне для любой книги: which sheet to use
, which columns to be Primary Key for the rows
; и which column in wbA for which column in wbB
(я назвал это wiring
), если нужно.
Есть также несколько дополнительных настроек, таких как замена строк. Иногда рабочие книги могут содержать строки, которые мне не нужны — я поддерживаю как регулярные выражения, так и буквальные замены для них.
Или имена столбцов, хотя я также позволяю пользователю решить, должна ли программа просто взять первую строку в sheetA
в качестве имен столбцов (что обычно и делается в таблицах данных), чтобы позже отобразить имена столбцов в файле результатов.
Я также слежу за тем, чтобы всякий раз, когда пользователю нужно вводить столбцы (например, установка столбцов PK), я позволял им вводить "A","B","C"
вместо номера столбца, такого как 1,2,3
. Я сам написал преобразование, для обобщения которого требуется немного математических вычислений, поскольку NPOI берет число, чтобы получить столбец из листа, но IIRC позже обнаружил, что NPOI уже имеет такие встроенные функции. Вы бы хотели сначала проверить, существуют ли они.
Json поддерживает массивы, поэтому, если вы хотите сравнить несколько листов между двумя книгами, вы можете попробовать использовать массив, чтобы выразить то, что вам нужно. Основная идея та же самая — каждый раз сравниваются два листа, поэтому вам нужно настроить для двух листов. Если есть несколько пар, измените формат конфигурации и сообщите своей программе, как их перебирать.
Если вам трудно это представить, отличная стратегия программирования — начать с простого. Вы начинаете с создания программы, которая может сравнивать две книги, сначала по одному листу в каждой книге, а затем постепенно добавлять в нее дополнительные функции, пока она в конечном итоге не будет соответствовать вашим реальным потребностям.
Я использую NPOI
для чтения Excel, а при получении содержимого ячейки я использую XSSFFormulaEvaluator.FormatCellValue()
- если я не могу получить книгу ячейки (cell.Row?.Sheet?.Workbook
возвращает ноль), поскольку FormulaEvaluator нуждается в ссылке на рабочую книгу происхождения ячейки, я использую просто cell.ToString()
.
Теперь для сравнения, это похоже на процесс, который вы написали в посте.
sheetB
, сделайте Dictionary<PK, row>
. Я просто объединил столбцы PK в строку, например pkA-pkB-pkC...
.List<string>
из Dictionary.Keys
. Список содержит sheetB
ключи.sheetA
сначала создайте первичный ключ, а затем найдите тот же ключ в словаре. Если не найдено, запишите это как ошибку. Если нашли, сравните и сделайте то, что нужно, а также уберите ключ из List<string>
. Вам не нужно создавать словари для обоих листов.List<string>
и запишите их как ошибки — sheetB
строка не найдена в sheetA
.. и т. д.Я вывожу результат сравнения в виде одного файла excel и копирую в него сравниваемые листы. Вывод состоит из трех листов: sheetA
, sheetB
и result
, поэтому пользователи могут быстро просматривать исходные листы при проверке результатов.
... удачи!
отличная информация и детали. спасибо за помощь. это очень ценится!!
Ключевым моментом здесь является обобщение вашей программы и разделение настроек на другие файлы, если вам нужно, поэтому, если впоследствии рабочие книги умножаются, вы все равно можете использовать ту же программу, поскольку процесс сравнения такой же - вам просто нужно сделать уверен, что он может делать петли.