#node.js #reactjs #exceljs #xlsm #sheetjs
Вопрос:
У меня есть проект узла, в котором мне нужен узел для создания нового файла XLSM, используя существующий файл XLSM в качестве шаблона. Шаблон содержит множество стилей, изображений и VBA. Приложение просто вставляет значения в несколько ячеек и сохраняет новый файл с незаметным именем.
Я пробовал XLSX и ExcelJS npm для достижения этой цели. Оба по-разному завершаются с ошибкой:
ExcelJS: похоже, в настоящее время не поддерживает запись файлов XLSM. Попытка сделать это приводит к повреждению файла.
XLSX: мне не удалось создать настоящую копию шаблона. Помимо прочего, в нем отсутствует форматирование и VBA. Это самый простой код, с которого я начинаю:
const templatePath = "C:/Users/rapsputinforever/Desktop/template.xlsm"
const directory = "C:/Users/rapsputinforever/Desktop"
const workbook = XLSX.readFile(templatePath);
// will insert data to some cells here
XLSX.writeFile(workbook, directory '/copy.xlsm');
Я знаю, что в этом пакете есть множество опций, которые, похоже, не связаны с проблемой, с которой я сталкиваюсь, и полезны для выполнения того, что на первый взгляд кажется очень простой задачей:
- Читать шаблон
- Добавление значений в ячейки
- Записывать как новый файл, сохраняя все VBA, стили и так далее
Я готов изучить другие пакеты, библиотеки и даже другие технологии. Этот инструмент является частью серверной части приложения React, однако я не уверен, что React сможет это сделать. Я открыт для любых советов. Я ценю помощь!
Комментарии:
1. Текущее решение, которое я рассматривал, — это выполнение «обходного пути», который дает те же результаты, используя npm ‘fs’ и excel VBA. Пользователь нажимает на кнопку «Отправить в шаблон» в узле React дублирует шаблон XLSM с помощью fs (надеюсь, сохраняет целостность файла) Узел создает CSV с нужными данными, сохраняется на локальном диске Пользователь получает дубликат файла при загрузке Пользователь открывает файл, нажимает на кнопку «Импорт», запускает VBA для поиска ииспользовать созданный CSV-файл Пользователь продолжает работать с шаблоном, который был разработан неуклюже, но так же, как и с использованием Excel, так что, конечно?
Ответ №1:
Я успешно решил проблему, разбив проблему на составные части. Зная о природе файлов Excel, что они представляют собой архивированные пакеты XML-файлов (источник здесь), тогда необходимо поэтапно выполнить следующие шаги:
- Создайте дубликат файла шаблона XLSM, копия имеет «.zip» в качестве расширения (‘fs’)
- Распакуйте zip-файл (‘extract-zip’)
- прочитайте SharedStrings.XML (‘fs’)
- Подсчитать количество итераций XML-тега » < s i > » в SharedStrings
Пример:
let stringCount = (sharedStrings.match(/<si>/g) || []).length;
- читать worksheet1.XML (или любые данные листа, которые должны быть вставлены)
- Найдите ячейку, найдя для нее тег. Если тег пустой, он будет выглядеть так:
Пример:
<c r="D10" s="29"/>
Обратите внимание, r = адрес ячейки, s = тег стиля, вы хотите сохранить оба на следующем шаге…
- Замените пустой тег ячейки флагом общей строки и желаемым индексом новой строки, которую нужно вставить.
Пример:
<c r="D9" s="29" t="s"><v>${stringCount}</v></c>
Подводя итог, мы заменяем XML-тег ячейки строкой insert, которая вставляется в файл SharedStrings и на которую ссылается индекс / количество этой новой строки. Это можно использовать в цикле для вставки массива значений, которые нужно вставить.
- Сохраните оба общих файла.XML и worksheet1.XML («fs»)
- Упакуйте незакрытую папку в новый архив («архиватор»)
- Переименуйте архивную папку с расширением ‘.XLSM’ (‘fs’)
- Очистка, удаление всех дубликатов zip-файлов / папок
Если обработка правильная, индекс sharedString является точным, если идентификатор стиля сохраняется, и при всех этих асинхронных действиях применяется правильная структура сценария, результирующий файл должен иметь желаемые результаты, поскольку целостность содержащего VBA, стилей, запросов, Изображений и т. Д. Была Сохраненасоздавая истинную копию и манипулируя составными частями этой копии.
Я начинающий разработчик, без сомнения, мой подход слишком длительный и неэффективный, и мое понимание того, почему это работает по сравнению с этими другими библиотеками, не основывается исключительно на моей интуиции. Я полагаю, что проблема в том, что ExcelJS и другие NPM создают рабочий лист «в буфере», который, к сожалению, содержит только любой элемент исходного файла, который эта библиотека учитывает на основе файлов XLSX. Если ExcelJS не просматривает VBA, то на новом листе не будет VBA, потому что, когда этот лист дублировался в буфере, он дублировал только все, что находилось в его области.
Я все еще очень открыт для дополнительных предложений / альтернатив / подходов / мудрости. Я надеюсь доработать это еще больше, чтобы оно было масштабируемым: я смог разработать это только для своего очень специфического приложения. Если мне удастся обобщить это и очистить свой код, я поделюсь фрагментом здесь.
Спасибо,
РЕДАКТИРОВАТЬ: Привет! Как оказалось, все не так просто! Несмотря на отсутствие ошибок при открытии файла, дубликат по-прежнему имеет некоторые фоновые проблемы, что становится очевидным, если вы используете Power Query для анализа указанных файлов XLSM. Кроме того, любая формула, которая ссылается на ячейки, заполненные решением узла, не будет обновляться при открытии файла. Чтобы решить эту проблему, запустите этот VBA:
Application.CalculateFullRebuild
Это обновит все формулы на каждом листе. После сохранения этого файла лист снова должен быть «нормальным». Рассматриваемая проблема основана на файле XML calcChain.XML .