2011-09-01 6 views
5

Hiện tại chúng tôi đang sử dụng bảng tổng hợp trong Excel 2003 để thực hiện báo cáo của mình. Các bảng tổng hợp này sử dụng chức năng Excel "Nhập dữ liệu ngoài" sẵn có để cung cấp các báo cáo từ SQL (SQL Server 2008 chính xác).Thay đổi Chuỗi kết nối "Dữ liệu Ngoài" của Excel

Báo cáo hiện tại trỏ vào cơ sở dữ liệu ở Vương quốc Anh của chúng tôi, nhưng bây giờ chúng tôi muốn tạo một bản sao của mỗi báo cáo trỏ đến cơ sở dữ liệu mới của Hoa Kỳ (có cùng lược đồ với cơ sở dữ liệu của Vương quốc Anh).

Thay vì cẩn thận đi qua gần 100 bảng tính, tôi hy vọng rằng sẽ có một chút tự động hóa COM mà tôi có thể sử dụng để thay đổi chuỗi kết nối trong mỗi bảng tính.

Có ai biết cách thay đổi chuỗi kết nối nguồn dữ liệu ngoài từ COM không?

Tôi đang sử dụng .Net (cụ thể là C#) nhưng tôi rất biết ơn vì bất kỳ trợ giúp nào bất kể ngôn ngữ hoặc phương thức (nó không phải là COM).

Trả lời

12

Sau khi xem các ví dụ VBA khác nhau và tài liệu MSDN COM tôi đã tìm ra cách thực hiện.

Phần quan trọng là các chuỗi kết nối được lưu giữ tại một trong hai vị trí tùy thuộc vào cách bạn tạo trang tính của mình.

  1. Nếu bạn đã sử dụng thuật sĩ bảng pivot thì chuỗi kết nối sẽ được lưu trữ trong bộ sưu tập được trả về bởi các chức năng Workbook.PivotCaches() (các đối tượng PivotCache trở có một tài sản, trong đó có kết nối chuỗi Connection) .

  2. Nếu bạn sử dụng "Nhập dữ liệu bên ngoài" các dây kết nối sẽ được lưu trữ trong bộ sưu tập được trả về bởi các Worksheet.QueryTables tài sản (các đối tượng QueryTable trở có một tài sản, trong đó có kết nối chuỗi Connection).

Có thể có nhiều nơi hơn mà chuỗi kết nối có thể được lưu trữ, đây là hai địa chỉ duy nhất mà tôi biết đến từ trước tới nay. Nếu bạn biết nữa, xin hãy để lại một số thông tin trong phần bình luận và tôi sẽ thêm vào câu trả lời.

Dưới đây là một độc đáo nhận xét đầy đủ làm việc C# ví dụ để giúp bất cứ ai khác mà đi qua vấn đề này:

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; 
}