我们目前在Excel 2003中使用数据透视表来执行报告。这些数据透视表使用内置的"导入外部数据"用于从SQL提供报表的Excel功能(准确地说是SQL Server 2008)。
报告目前指向我们的英国数据库,但我们现在想要制作指向我们新的美国数据库(与英国数据库具有相同架构)的每份报告的副本。
我希望能够使用很多COM自动化来改变每个电子表格中的连接字符串,而不是苦心经历近100个电子表格。
有没有人知道从COM更改外部数据源连接字符串的方法?
我正在使用.Net(特别是C#),但我感激任何帮助,无论语言或方法如何(它不必是COM)。
答案 0 :(得分:13)
在查看各种VBA示例和MSDN COM文档之后,我已经想出了如何做到这一点。
重要的是,连接字符串保存在两个位置之一,具体取决于您创建工作表的方式。
如果您已使用数据透视表向导,则使用连接字符串
将存储在由...返回的集合中
Workbook.PivotCaches()
函数(PivotCache对象
返回有一个Connection
属性,其中包含连接
字符串)。
如果使用“导入外部数据”,则连接字符串将为
存储在由...返回的集合中
Worksheet.QueryTables
属性(QueryTable对象
返回有一个Connection
属性,其中包含连接
字符串)。
可能存在更多可以存储Connection字符串的地方,这些是我目前唯一知道的两个。如果您知道更多信息,请在评论中留下一些信息,我会加入答案。
这是一个很好评论的完整工作C#示例,可以帮助遇到此问题的其他人:
static void ChangeConnectionStrings(string directoryName, string oldServerName, string newServerName)
{
var directory = new DirectoryInfo(directoryName);
//get all the excel files from the directory
var files = directory.GetFiles("*.xls", SearchOption.AllDirectories);
Microsoft.Office.Interop.Excel.Application application = null;
try
{
//create a new application
application = new Microsoft.Office.Interop.Excel.Application();
//go through each excel file
foreach (var file in files)
{
//open the file
application.Workbooks.Open(file.FullName);
//get the query tables from the worksheets
var sheets = application.Sheets.OfType<Worksheet>();
var queryTables = sheets.SelectMany(s => GetQueryTables(s));
//change the connection string for any query tables
foreach (var queryTable in queryTables)
{
queryTable.Connection = queryTable.Connection.Replace(oldServerName, newServerName);
}
//get the pivot table data from the workbooks
var workbooks = application.Workbooks.Cast<Workbook>();
var pivotCaches = workbooks.SelectMany(w => GetPivotCaches(w));
//change the connection string for any pivot tables
foreach (var pivotCache in pivotCaches)
{
pivotCache.Connection = pivotCache.Connection.Replace(oldServerName, newServerName);
}
Console.WriteLine("Saving " + file.Name);
//save the changes
foreach (var workbook in workbooks)
{
workbook.Save();
workbook.Close();
}
}
}
finally
{
//make sure we quit the application
if (application != null)
application.Quit();
}
}
//PivotCaches isn't Enumerable so we can't just use Cast<PivotCache>, therefore we need a helper function
static IEnumerable<PivotCache> GetPivotCaches(Workbook workbook)
{
foreach (PivotCache pivotCache in workbook.PivotCaches())
yield return pivotCache;
}
//QueryTables isn't Enumerable so we can't just use Cast<QueryTable>, therefore we need a helper function
static IEnumerable<QueryTable> GetQueryTables(Worksheet worksheet)
{
foreach (QueryTable queryTable in worksheet.QueryTables)
yield return queryTable;
}