更改Excel“外部数据”连接字符串

时间:2011-09-01 09:06:57

标签: .net com excel-2003

我们目前在Excel 2003中使用数据透视表来执行报告。这些数据透视表使用内置的"导入外部数据"用于从SQL提供报表的Excel功能(准确地说是SQL Server 2008)。

报告目前指向我们的英国数据库,但我们现在想要制作指向我们新的美国数据库(与英国数据库具有相同架构)的每份报告的副本。

我希望能够使用很多COM自动化来改变每个电子表格中的连接字符串,而不是苦心经历近100个电子表格。

有没有人知道从COM更改外部数据源连接字符串的方法?

我正在使用.Net(特别是C#),但我感激任何帮助,无论语言或方法如何(它不必是COM)。

1 个答案:

答案 0 :(得分:13)

在查看各种VBA示例和MSDN COM文档之后,我已经想出了如何做到这一点。

重要的是,连接字符串保存在两个位置之一,具体取决于您创建工作表的方式。

  1. 如果您已使用数据透视表向导,则使用连接字符串 将存储在由...返回的集合中 Workbook.PivotCaches()函数(PivotCache对象 返回有一个Connection属性,其中包含连接 字符串)。

  2. 如果使用“导入外部数据”,则连接字符串将为 存储在由...返回的集合中 Worksheet.QueryTables属性(QueryTable对象 返回有一个Connection属性,其中包含连接 字符串)。

  3. 可能存在更多可以存储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;
    }