В итоге я использовал следующий подход. Хотя это не совсем c#, и я надеюсь, что когда-нибудь найду лучшее решение. Документация VSTO действительно нестандартная.
public void addQuery(string m_script_path, string query_name, Excel.Workbook wk)
{
VBComponent newStandardModule;
if(wk.VBProject.VBComponents.Count==0){
newStandardModule = wk.VBProject.VBComponents.Add(Microsoft.Vbe.Interop.vbext_ComponentType.vbext_ct_StdModule);
}
else
{
newStandardModule = wk.VBProject.VBComponents.Item(1);
}
var codeModule = newStandardModule.CodeModule;
// add vba code to module
var lineNum = codeModule.CountOfLines + 1;
var macroName = "addQuery";
var codeText = "Public Sub " + macroName + "()" + "\r\n";
codeText += "M_Script = CreateObject(\"Scripting.FileSystemObject\").OpenTextFile(\""+m_script_path+"\", 1).ReadAll" + "\r\n";
codeText += "ActiveWorkbook.Queries.Add Name:=\""+ query_name+"\", Formula:=M_Script\r\n";
codeText += "ActiveWorkbook.Connections.Add2 _\r\n";
codeText += "\"Query - test\", _\r\n";
codeText += "\"Connection to the '" + query_name + "' query in the workbook.\", _\r\n";
codeText += "\"OLEDB;Provider=Microsoft.Mashup.OleDb.1;Data Source=$Workbook$;Location=" + query_name + ";Extended Properties=\" _\r\n";
codeText += ", \"\"\"" + query_name + "\"\"\", 6, True, False\r\n";
codeText += "End Sub";
codeModule.InsertLines(lineNum, codeText);
var macro = string.Format("{0}.{1}", newStandardModule.Name, macroName);
wk.Application.Run(macro);
codeModule.DeleteLines(lineNum, 9);
}