我必须首先说我一般都不熟悉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列,所以我将其添加到伪代码中。
答案 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;
}
}
}