【问题标题】:How to Concatenate All Worksheets of a Workbook In Excel如何在Excel中连接工作簿的所有工作表
【发布时间】:2025-11-26 14:30:01
【问题描述】:

我必须首先说我对 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 列,所以我将其添加到伪代码中。

【问题讨论】:

  • 啊——太接近了。这基本上就是我要寻找的,但两者都假设标题在整个工作表中是一致的。每个工作表中的标题都不完全相同。它们是配件的名称。

标签: c# excel merge office-interop


【解决方案1】:

在对 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 互操作类,我在这里找到了相关信息:

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

【讨论】: