如何在Excel中连接工作簿的所有工作表

时间:2014-01-09 21:52:16

标签: c# excel merge office-interop

我必须首先说我一般都不熟悉VBA或宏。

我有一个Excel文件,其中包含一些“基本项目”的单独工作表。

每个工作表都包含产品和附件之间的关系。数字(如果为0)表示其不兼容,并且任何数字> 0,是产品可以配备的附件数量。

每个工作表包含不同的附件和代码,但可能会出现一些重复。

数据的一个例子:

|            | J0021       | J0022        |
|:-----------|------------:|:------------:|
| Product 1  |     1       |      1       |
| Product 2  |     1       |      2       |
| Product 3  |     1       |      1       |
| Product 4  |     0       |      0       |
| Product 5  |     0       |      1       |
| Product 6  |     1       |      0       |

共有43个独立的工作表,其中500到2000个单元表示关系。

我想的是只有一对一的表格,用以下方式表示关系:

Table Name: ProductAccessoryCompat

 Id (Primary Key)   | ProductId (Foreign Key) | AccessoryId(Foreign Key) | Count
 -------------------|-------------------------|--------------------------|------
 LB1 (ProdBase+Num) |         Product 1       |  J0021                   |   1  
 LB2                |         Product 1       |  J0022                   |   1  
 FV1                |         Product 2       |  J0021                   |   1  
 FV2                |         Product 2       |  J0022                   |   2  
 BG1                |         Product 3       |  J0021                   |   1  
 BG2                |         Product 3       |  J0022                   |   1  
 HG1                |         Product 4       |  J0021                   |   0  
 HG2                |         Product 4       |  J0022                   |   0  
 JJ1                |         Product 5       |  J0021                   |   0  
 JJ2                |         Product 5       |  J0022                   |   1  
 JL1                |         Product 6       |  J0021                   |   1  
 JL2                |         Product 6       |  J0022                   |   0  

工作表具有相同类型的数据,但会有不同的产品列和不同的行。

我知道我需要将它们连接成一个工作表,然后将其导出为CSV,然后将该CSV导入MySQL。

有没有人可以帮我确定如何将不同的工作表连接成一个格式,我已经为我要创建的表格描述了这个格式?

我认为它会像以下天真的伪代码:

var NumOfSheets = Workbook.Worksheets.Count;
var newSheet = Workbook.CreateSheet();
for (i = 0; i < NumOfSheets; i++)
{
    var curSheet = Workbook.GetSheet(i);
    curSheet.Activate;

    var numColumns = curSheet.Columns.Count;
    var numRows = curSheet.Rows.Count;
    var relationships = new Dictionary<string, string>();

    for (j = 0; j < numRows; j++)
    {
        var currentProd = curSheet.getCell(j, 0);

        for(k = 0; k < numColumns; j++)
        {
            var currentAcc = curSheet.getCell(0, k);
            var relationship = curSheet.getCell(j, k);
            if (relationship != 0) var relationships[currentProd][currentAcc] = relationship;
        }
    }
}

[Then iterate through the 2D associative array, inserting
 a new row for each product, and a new column for each
 accessory that each do net yet exist on the spreadsheet.]

我几乎认为手工操作会更容易,但你知道,懒惰会赢。

编辑:我刚刚意识到我可能只是忽略0列,所以我将其添加到伪代码中。

1 个答案:

答案 0 :(得分:0)

在对VBA进行一些搞乱之后,我决定不想走那条路,然后启动Visual Studio来使用C#编写我的解决方案。

我的一位朋友指出,我可以使用ADO.NET打开并使用SQL语法读取Excel文件。

我这样做了,事情很顺利,直到把我的按摩数据重写成新的工作表为止。

使用ADO.NET并写入Excel时会出现一个错误,导致写入单元格的字符串前面有一个撇号。 (例如“'derp'而不是”derp“)。

您可以找到有关at this Microsoft link: How To Use ADO with Excel Data from Visual Basic or VBA

的信息

我最终使用了Office Interop类,我在这里找到了相关信息:

How to automate Microsoft Excel from Microsoft Visual C#.NET

我要发布我真正天真的尝试。虽然它是成功的并且执行了我需要的确切功能,但是有人可能能够查看它并在以后采集有用的东西。

*注意!这对我来说只是一次性的事情 - 我不打算重用这段代码,所以这很糟糕。遗憾。

没有进一步的麻烦:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Data;
using System.Data.OleDb;
using Excel = Microsoft.Office.Interop.Excel;

namespace ConsolidateAccProdExcel
{
    class Program
    {
        static void Main(string[] args)
        {
            string sheetPath = @"PATH-TO-FILE";
            string connectionString = string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0}; Extended Properties=\"Excel 12.0 Macro;HDR=YES;IMEX=1\"",sheetPath);

            Dictionary<string, Dictionary<string, string>> relationshipDictionary = new Dictionary<string, Dictionary<string, string>>();

            using (OleDbConnection oleConnection = new OleDbConnection(connectionString))
            {
                oleConnection.Open();
                System.Data.DataTable dt = oleConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);

                List<DataTable> listDt = new List<DataTable>();

                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    listDt.Add(GetWorksheetData(oleConnection, (string)dt.Rows[i]["TABLE_NAME"]));
                }

                List<DataRow> rowList = new List<DataRow>();

                for (int i = 0; i < listDt.Count; i++)
                {
                    DataColumnCollection dtColumns = listDt[i].Columns;
                    foreach (DataRow drRow in listDt[i].Rows)
                    {
                        if (!(drRow.ItemArray[0] is DBNull))
                        {
                            Dictionary<string, string> accessoryData = new Dictionary<string, string>();
                            string rowName = (string)drRow.ItemArray[0];
                            for (int j = 1; j < drRow.ItemArray.Length; j++)
                            {
                                if ((string)drRow.ItemArray[j].ToString() != 0.ToString()) accessoryData.Add(dtColumns[j].ColumnName, (string)drRow.ItemArray[j].ToString());
                            }
                            try { relationshipDictionary.Add(rowName, accessoryData); }
                            catch (ArgumentException e) { Trace.WriteLine("problem: " + rowName); }
                        }
                    }
                }

                writeConcatenatedSheets(relationshipDictionary, oleConnection);
            }

            long relationshipsCount = 0;

            foreach (KeyValuePair<string, Dictionary<string, string>> product in relationshipDictionary)
            {
                relationshipsCount += product.Value.Count;
            }
            Trace.WriteLine(relationshipsCount);

        }

        private static void writeConcatenatedSheets(Dictionary<string, Dictionary<string, string>> relationshipDictionary, OleDbConnection connection)
        {
            int relationshipsCount = 0;

            foreach (KeyValuePair<string, Dictionary<string, string>> product in relationshipDictionary)
            {
                relationshipsCount += product.Value.Count;
            }

            int currentCount = 1;
            string writeCommand = "";

            Excel.Application app = new Excel.Application();
            app.Visible = true;

            Excel.Workbook workbook = app.Workbooks.Open(@"PATH-TO-FILE");
            Excel.Sheets excelSheets = workbook.Worksheets;

            Excel.Worksheet consolidateSheet = (Excel.Worksheet)excelSheets.get_Item("Consolidated Data");

            Excel.Range rows = consolidateSheet.Rows;

            int count = rows.Count;

            foreach (KeyValuePair<string, Dictionary<string, string>> product in relationshipDictionary)
            {
                int productCount = 0;
                foreach (KeyValuePair<string, string> accessory in product.Value)
                {
                    string[,] values = new string[1,4];
                    values[0,0] = product.Key + "_[" + productCount + "]";
                    values[0,1] = product.Key;
                    values[0,2] = accessory.Key;
                    values[0,3] = accessory.Value;

                    rows.get_Range("A" + currentCount, "D" + currentCount).Value2 = values;

                    ++productCount;
                    ++currentCount;
                }
            }

            connection.Close();
        }

        private static DataTable GetWorksheetData(OleDbConnection oleConnection, string SheetName)
        {
            DataTable dt = new DataTable();
            OleDbDataAdapter odba = new OleDbDataAdapter(string.Format ("SELECT * FROM [{0}]",SheetName), oleConnection);
            odba.Fill(dt);
            return dt;
        }
    }
}