Добавление файла макроса в файл XLSX/XLSM с помощью Packaging
Я использую System.IO.Packaging
создавать простые файлы Excel. Один из наших клиентов хотел бы иметь макрос автозапуска, который обновляет данные и пересчитывает лист.
Разбирая существующие листы, я вижу, что все, что вам нужно сделать, это добавить vbaProject.bin
файл и измените несколько типов в _rels. Итак, я сделал макрос в одном файле, извлек vbaProject.bin
скопировал его в другой файл, и вот, вот макрос.
Я знаю, как добавлять части пакета, когда они в формате XML, такие как листы или сама книга, но я никогда не добавлял двоичный файл и не могу понять это. Кто-нибудь делал это раньше?
1 ответ
Ладно, я понял. Следуя предложению TnTinMn:
Откройте новую книгу и введите свой макрос. Измените расширение на zip, откройте его, откройте
xl
папку и скопироватьvbaProject.bin
где-то легко найти.В своем коде.Net создайте новую деталь и добавьте ее в пакет как "xl/vbaProject.bin". Копировать побайтово из
vbaProject.bin
Вы извлечены выше. Он будет сжат при добавлении байтов.Затем вы должны добавить отношение к книге, которое указывает на ваш новый файл. Вы можете найти эти отношения в
xl/_rels/workbook.xml.rels
,Вы также должны добавить запись типа контента в корне документа, которая идет в
[Content Types].xls
, Это происходит автоматически при использовании параметра ContentType CreatePartИ наконец, измените расширение на.xlsm или.xltm
Я извлекаю следующее из многих мест в моем коде, так что это псевдо...
'the package...
Dim xlPackage As Package = Package.Open(WBStream, FileMode.Create)
'start with the workbook, we need the object before we physically insert it
Dim xlPartUri As URI = PackUriHelper.CreatePartUri(New Uri(GetAbsoluteTargetUri("/", "xl/workbook.xml"), UriKind.Relative)) 'the URI is relative to the outermost part of the package, /
Dim xlPart As PackagePart = xlPackage.CreatePart(xlPartUri, "application/vnd.ms-excel.sheet.macroEnabled.main+xml", CompressionOption.Normal)
'add an entry in the root _rels folder pointing to the workbook
xlPackage.CreateRelationship(xlPartUri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument", "xlWorkbook") 'it turns out the ID can be anything unique
'now that we have the WB part, we can make our macro relative to it
Dim xlMacroUri As URI = PackUriHelper.CreatePartUri(New Uri(GetAbsoluteTargetUri("/xl/workbook.xml", "vbaProject.bin"), UriKind.Relative))
Dim xlMacroPart as PackagePart = xlPackage.CreatePart(xlPartUri, "application/vnd.ms-office.vbaProject", CompressionOption.Normal)
'time we link the vba to the workbook
xlParentPart.CreateRelationship(xlPartUri, TargetMode.Internal, "http://schemas.microsoft.com/office/2006/relationships/vbaProject", "rIdMacro") 'the ID on the macro can be anything as well
'copy over the data from the macro file
Using MacroStream As New FileStream("C:\yourdirectory\vbaProject.bin", FileMode.Open, FileAccess.Read)
MacroStream.CopyTo(xlMacroPart.GetStream())
End Using
'
'now write data into the main workbook any way you like, likely using new Parts to add Sheets