2012-03-14 4 views
3

Я могу успешно вставить часть кода VBA в созданную книгу excel, но то, что я пытаюсь сделать, это использовать событие Workbook_Open(), чтобы код VBA выполнялся при открытии файла. Я добавляю sub к объекту «ThisWorkbook» в моем файле шаблона xlsm. Затем я использую инструмент повышения производительности openxml для отражения кода и получения закодированных данных VBA.OpenXML SDK Inject VBA в excel workbook

Когда файл сгенерирован и я просматриваю VBA, я вижу объекты «ThisWorkbook» и «ThisWorkbook1». Мой VBA находится в объекте «ThisWorkbook», но код никогда не запускается при открытии. Если я переведу свой код VBA в «ThisWorkbook1» и снова открою файл, он отлично работает. Почему добавлена ​​дополнительная «ThisWorkbook»? Невозможно ли вставить таблицу Excel с помощью Workbook_Open()? Вот фрагмент кода C#, который я использую:

private string partData = "..."; //base 64 encoded data from reflection code 
//open workbook, myWorkbook 
VbaProjectPart newPart = myWorkbook.WorkbookPart.AddNewPart<VbaProjectPart>("rId1"); 
System.IO.Stream data = GetBinaryDataStream(partData); 
newPart.FeedData(data); 
data.Close(); 
//save and close workbook 

У кого-нибудь есть идеи?

+0

В редакторе VBA, когда вы щелкаете правой кнопкой мыши по этой книге и этой книге 1, есть ли у вас ** Удалить эту книгу ... ** выделен серым цветом? –

ответ

3

Основываясь на моих исследованиях, нет способа вставить данные детали проекта в формате, который можно манипулировать на C#. В формате OpenXML проект VBA по-прежнему сохраняется в двоичном формате. Однако копирование VbaProjectPart из одного документа Excel в другое должно работать. В результате вам нужно будет определить, что вы хотели, чтобы часть проекта говорила заранее.

Если все в порядке с этим, то вы можете добавить следующий код в файл шаблона Excel в объекте Microsoft Excel «ThisWorkbook», вместе с соответствующим кодом макроса:

Private Sub Workbook_Open() 
    Run "Module1.SomeMacroName()" 
End Sub 

Чтобы скопировать VbaProjectPart объект из одного файла в другой, вы бы использовали такой код:

public static void InsertVbaPart() 
{ 
    using(SpreadsheetDocument ssDoc = SpreadsheetDocument.Open("file1.xlsm", false)) 
    { 
     WorkbookPart wbPart = ssDoc.WorkbookPart; 
     MemoryStream ms; 
     CopyStream(ssDoc.WorkbookPart.VbaProjectPart.GetStream(), ms); 

     using(SpreadsheetDocument ssDoc2 = SpreadsheetDocument.Open("file2.xlsm", true)) 
     { 
      Stream stream = ssDoc2.WorkbookPart.VbaProjectPart.GetStream(); 
      ms.WriteTo(stream); 
     } 
    } 
} 

public static void CopyStream(Stream input, Stream output) 
{ 
    byte[] buffer = new byte[short.MaxValue + 1]; 
    while (true) 
    { 
     int read = input.Read(buffer, 0, buffer.Length); 
     if (read <= 0) 
      return; 
     output.Write(buffer, 0, read); 
    } 
} 

Надеюсь, что это поможет.

+0

Я также должен добавить, что после написания я столкнулся с платформой под названием [ClosedXML] (http://closedxml.codeplex.com/). Он разработан специально для взаимодействия с файлами OpenXML Excel и очень интуитивно понятен, он также может помочь. – Lentonator

Смежные вопросы