Изменить строку подключения Excel "Внешние данные" - PullRequest
8 голосов
/ 01 сентября 2011

В настоящее время мы используем сводные таблицы в Excel 2003 для составления наших отчетов.Эти сводные таблицы используют встроенную функцию Excel «Импорт внешних данных» для подачи отчетов из SQL (точнее, SQL Server 2008).

Отчеты в настоящее время указывают на нашу базу данных в Великобритании, но теперь мы хотели бысделайте копию каждого отчета, который указывает на нашу новую базу данных в США (которая имеет ту же схему, что и база данных в Великобритании).

Вместо того, чтобы кропотливо пройтись почти по 100 таблицам, я надеялся, что будет неплохоАвтоматизация COM, которую я мог бы использовать для изменения строк подключения в каждой из электронных таблиц.

Кто-нибудь знает способ изменить строку подключения внешнего источника данных с COM?

Я использую.Net (в частности, C #), но я был бы благодарен за любую помощь независимо от языка или метода (это не обязательно должен быть COM).

1 Ответ

13 голосов
/ 01 сентября 2011

Изучив различные примеры VBA и документацию MSDN COM, я понял, как это сделать.

Важной частью является то, что строки подключения хранятся в одном из двух мест, в зависимости от того, как вы создали свой лист.

  1. Если вы использовали мастер сводных таблиц, то строки подключения будет храниться в коллекции, возвращенной Workbook.PivotCaches() функция (объекты PivotCache возвращаемое свойство Connection содержит соединение строка).

  2. Если вы использовали «Импорт внешних данных», строки подключения будут хранится в коллекции, возвращенной Worksheet.QueryTables свойство (объекты QueryTable возвращено свойство 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;
}
...