我有一个 SSIS 包,我必须从 Excel 工作表中选择一些值并将它们插入到 SQL Server 数据库表中,我是通过执行 sql 任务来完成的。
步骤如下:
- 从映射表中选择所有记录,单元格位置是动态的,因此将其保留在 SQL 表中(大约有 3000 个单元格 - 我们必须从 Excel 中的选择性字段中选取值,而不是全部)
示例:
在每条记录上迭代
Foreach
使用单元格名称和工作表名称创建查询
示例:
从 [GenDet$F3:F3] 中选择 *
执行查询以从 Excel 工作表中获取该单元格的值
示例:
- 将值插入 SQL 数据库表
它正在工作 - 但问题是它所花费的时间。对于 3000 个字段,处理一个 Excel 文件需要 50 分钟。我必须在一分钟之内完成此操作。
请让我知道实现此目标的最佳方法。
谢谢!
最佳答案
正如我在评论中提到的,我认为编写一个 C# 脚本从 Excel 单元格读取数据并将它们分组到列表或 DataTable 中,然后执行一次批量插入会更高效
C# 应用程序/脚本任务
所需的组件
首先您必须导入 Excel Interop 程序集:
using Microsoft.Office.Interop.Excel;
using System.Data.SqlClient;
将列标题字母转换为索引
现在您应该定义以下函数,将 Excel 列字母表转换为索引:
private int ParseColHeaderToIndex(string colAdress)
{
int[] digits = new int[colAdress.Length];
for (int i = 0; i < colAdress.Length; i++)
{
digits[i] = Convert.ToInt32(colAdress[i]) - 64;
}
int mul = 1;
int res = 0;
for (int pos = digits.Length - 1; pos >= 0; pos--)
{
res += digits[pos] * mul;
mul *= 26;
}
return res;
}
SQL批量插入功能
以下函数是对SQL执行批量插入操作
public void InsertToSQLUsingSQLBulk(System.Data.DataTable dt, string connectionstring, string Tablename)
{
try
{
using (var bulkCopy = new SqlBulkCopy(connectionstring, SqlBulkCopyOptions.KeepIdentity))
{
foreach (DataColumn col in dt.Columns)
{
bulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);
}
bulkCopy.BulkCopyTimeout = 600;
bulkCopy.DestinationTableName = Tablename;
bulkCopy.WriteToServer(dt);
}
}
catch (Exception ex)
{
throw ex;
}
}
从 Excel 读取到目标 DataTable
以下函数采用 Excel 路径和范围 DataTable 作为参数,并返回具有目标结构的 DataTable(Id, AttributeKey, AttributeValue)
public System.Data.DataTable ReadFromExcel(System.Data.DataTable dtRanges,string strPath)
{
string num = "0123456789";
//Declare result datatable
System.Data.DataTable destination = new System.Data.DataTable();
destination.Columns.Add("Id");
destination.Columns.Add("AttributeKey");
destination.Columns.Add("AttributeValue");
//Decalre Interop Objects
Microsoft.Office.Interop.Excel.Application m_XlApp;
m_XlApp = new Microsoft.Office.Interop.Excel.Application();
m_XlApp.Visible = false;
m_XlApp.DisplayAlerts = false;
Workbook xlWbs = null;
xlWbs = m_XlApp.Workbooks.Open(strPath, Type.Missing, Type.Missing,
Type.Missing, "'", Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing, Type.Missing,
Type.Missing, Type.Missing);
xlWbs.DoNotPromptForConvert = true;
xlWbs.CheckCompatibility = false;
xlWbs.Application.DisplayAlerts = false;
//Loop over worksheets
foreach (Worksheet xlWks in xlWbs.Worksheets) {
string Name = xlWks.Name;
//Assing rows relevant to the current sheet
foreach (DataRow drRow in dtRanges.AsEnumerable().Where(x => x["Sheet_Name"].ToString() == Name))
{
string sheet = drRow["Sheet_Name"].ToString();
string range = drRow["Location_Value"].ToString();
string field = drRow["Field_Name"].ToString();
string id = drRow["Id"].ToString();
string rangeAlpha = range.Split(':')[0];
int rowidx = 0;
int colidx = 0;
foreach (char chr in num) {
rangeAlpha = rangeAlpha.Replace(chr, '\0');
}
rowidx = Int32.Parse(range.Split(':')[0].Replace(rangeAlpha, ""));
colidx = ParseColHeaderToIndex(rangeAlpha);
DataRow dr = destination.NewRow();
if (xlWks.Cells[rowidx, colidx] != null && (xlWks.Cells[rowidx, colidx] as Range).Value2 != null)
{
dr["AttributeValue"] = (string)(xlWks.Cells[rowidx, colidx] as Range).Value2;
}
else
{
dr["AttributeValue"] = "";
}
dr["AttributeKey"] = drRow["Field_Name"].ToString();
dr["Id"] = drRow["Id"].ToString();
destination.Rows.Add(dr);
}
}
xlWbs.Close(false, Type.Missing, Type.Missing);
m_XlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWbs);
System.Runtime.InteropServices.Marshal.ReleaseComObject(m_XlApp);
return destination;
}
主程序
public void Main(){
//Initialize ranges table
System.Data.DataTable ranges = new System.Data.DataTable();
ranges.Columns.Add("Id");
ranges.Columns.Add("Field_Name");
ranges.Columns.Add("Location_Value");
ranges.Columns.Add("Sheet_Name");
//Add rows or read them from database using SQLDataAdapter
//note that the destination table must exists in the database with identical columns of datatable
System.Data.DataTable destination = ReadFromExcel(ranges, "C:\\1.xlsx", "dbo.destination");
InsertToSQLUsingSQLBulk(destination, "Pass SQL Server destination connection string here");
}
<小时/>
更新 1 - 提高性能
您可以通过将所有工作表内容放入二维数组中,然后循环数组而不是在 Excel 工作表内循环来提高方法性能。
Excel.Range targetCells = xlWks.UsedRange;
object[,] allValues = (object[,])targetCells.Cells.Value;
...
if (targetCells.Cells[rowidx, colidx] != null)
{
dr["AttributeValue"] = (string)(targetCells.Cells[rowidx, colidx] as Range).Value2;
}
else
{
dr["AttributeValue"] = "";
}
引用
关于sql - 根据单元格位置将选择性字段从 Excel 批量插入到 SQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55009040/