我有一个小程序,您可以在其中选择一些数据库表并创建一个包含每个表的所有值的Excel文件,这就是我创建excel文件的解决方案。
foreach (var selectedDatabase in this.lstSourceDatabaseTables.SelectedItems)
{
//creates a new worksheet foreach selected table
foreach (TableRetrieverItem databaseTable in tableItems.FindAll(e => e.TableName.Equals(selectedDatabase)))
{
_xlWorksheet = (Excel.Worksheet) xlApp.Worksheets.Add();
_xlWorksheet.Name = databaseTable.TableName.Length > 31 ? databaseTable.TableName.Substring(0, 31): databaseTable.TableName;
_xlWorksheet.Cells[1, 1] = string.Format("{0}.{1}", databaseTable.TableOwner,databaseTable.TableName);
ColumnRetriever retrieveColumn = new ColumnRetriever(SourceConnectionString);
IEnumerable<ColumnRetrieverItem> dbColumns = retrieveColumn.RetrieveColumns(databaseTable.TableName);
var results = retrieveColumn.GetValues(databaseTable.TableName);
int i = 1;
(result is a result.Item3 is a List<List<string>> which contains all values from a table and for each row is a new list inserted)
for (int j = 0; j < results.Item3.Count(); j++)
{
int tmp = 1;
foreach (var value in results.Item3[j])
{
_xlWorksheet.Cells[j + 3, tmp] = value;
tmp++;
}
}
}
}
它可以工作但是当你有一个5000或更多值的表时,它将需要很长时间。
有人可能知道每行添加列表列表字符串比使用foreach解决方案更好的解决方案吗?
答案 0 :(得分:1)
我利用代码示例中的GetExcelColumnName
函数将列数转换为excel列名。
整个想法是,逐个编写excel单元格的速度非常慢。因此,预先计算整个值表,然后在单个操作中分配结果。要将值指定给二维范围,请使用二维值数组:
var rows = results.Item3.Count;
var cols = results.Item3.Max(x => x.Count);
object[,] values = new object[rows, cols];
// TODO: initialize values from results content
// get the appropriate range
Range range = w.Range["A3", GetExcelColumnName(cols) + (rows + 2)];
// assign all values at once
range.Value = values;
也许您需要更改有关已使用索引范围的一些详细信息 - 无法立即测试我的代码。
答案 1 :(得分:1)
正如我所见,你没有做过剖析。我建议首先进行性能分析(例如dotTrace)并查看代码的哪些部分会导致性能问题。 在我的实践中,当代码执行速度慢于数据库请求时,极少数情况下(几乎没有这种情况),即使代码在算法术语中非常糟糕。
首先,我建议不要按列填充excel,而是按行填充。如果您的表有很多列,这将导致多次往返数据库 - 这对性能影响很大。
其次,按行分批写入excel。将excel文件视为迷你数据库,使用相同的批次比一个接一个地快。原理