我有一个包含多个列的DataTable,包括AccountNumber,Year和Month。我将此表中的信息导出到Excel工作簿。由于这个表有可能非常大,我必须检查表中的记录数(因为Excel只能有65536行或类似的东西。如果原始表足够小,我需要放入所有记录在一个工作表中。如果一个工作表的记录太多,我需要根据AccountNumber将记录分成多个工作表。另外,如果特定AccountNumber的记录太多,那么我需要将该AccountNumber分成多个工作表基于年份。如果特定年份仍有太多记录,那么我必须按月拆分。
例如:
如果我总共有500,000条记录,我必须按AccountNumber分割它们:
工作表名称----记录数
然后我需要将Account 1111和3333分成多个基于Year的工作表。我会有这样的事情:
工作表名称----记录数
然后,由于1111 - 2011仍然太大,我将不得不根据月份拆分那个,最后给出:
工作表名称----记录数
用于创建Excel文件的代码是由我公司编写的项目。为简单起见,该函数接受DataTable并以Excel电子表格的格式写出DataTable中的记录。关于如何在不再调用数据库的情况下执行此操作的任何想法?提前谢谢。
答案 0 :(得分:0)
您是否专门为此操作从数据库中提取数据?如果是这样,请使用SELECT DISTINCT并在相关列上放置数据库索引。这样,您无需担心它 - DBMS将为您过滤掉重复的行。您仍需要做的就是遍历行并根据需要对它们进行分组。
如果您正在努力对行进行分组,可以将COUNT()添加到select和group by子句中,DBMS将告诉您适合该类别的行数:
SELECT *, COUNT(*)AS row_count GROUP BY accountid, year, month, etc...;
你的行看起来如此:
c1 c2 c3 row_count
---- ---- ---- ---------
xxx, xxx, xxx, 1
yyy, yyy, yyy, 2
yyy, yyy, zzz, 2
答案 1 :(得分:0)
您可以使用LINQ-to-DataSet相应地对DataRows
进行分组,并将其添加到单独的DataTables
中,行数少于65536。
看看这个工作样本,它也会生成正确的文件/数据表名称:
Private Shared sampleAccountNumbers As List(Of Int32) = {1111, 2222, 3333, 4444}.ToList
Private Const MAX_ROWS = 65536
Private tblSource As New DataTable()
Private allResultTables As New List(Of DataTable)
Private Sub SplitTableRows()
Dim accQuery = _
From row In tblSource
Group row By AccountNumber = row("AccountNumber") Into AccNumGroup = Group
For Each acc In accQuery
If acc.AccNumGroup.Count > MAX_ROWS Then
Dim yearQuery = _
From row In acc.AccNumGroup
Group row By Year = row("Year") Into YearGroup = Group
For Each y In yearQuery
If y.YearGroup.Count > MAX_ROWS Then
Dim monthQuery = _
From row In y.YearGroup
Group row By Month = row("Month") Into MonthGroup = Group
For Each m In monthQuery
If m.MonthGroup.Count > MAX_ROWS Then
'split by days or whatever...'
Else
Dim tblMonth = m.MonthGroup.CopyToDataTable()
tblMonth.TableName = String.Format("{0}-{1}{2}", acc.AccountNumber, y.Year, m.Month)
allResultTables.Add(tblMonth)
End If
Next
Else
Dim tblYear = y.YearGroup.CopyToDataTable()
tblYear.TableName = String.Format("{0}-{1}", acc.AccountNumber, y.Year)
allResultTables.Add(tblYear)
End If
Next
Else
Dim tblAcc = acc.AccNumGroup.CopyToDataTable()
tblAcc.TableName = acc.AccountNumber
allResultTables.Add(tblAcc)
End If
Next
End Sub
Private Sub BtnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnStart.Click
InitSourceDataTable()
If tblSource.Rows.Count > MAX_ROWS Then
SplitTableRows()
Else
allResultTables.Add(tblSource)
End If
For Each tbl In allResultTables
'call your generate-excel-method...'
Next
End Sub
Private Sub InitSourceDataTable()
Dim rndAccNum As New Random(Date.Now.Millisecond)
Dim rndYear As New Random(Date.Now.Millisecond)
Dim rndMonth As New Random(Date.Now.Millisecond)
tblSource.Columns.Add(New DataColumn("ID", GetType(Integer)))
tblSource.Columns.Add(New DataColumn("AccountNumber", GetType(Integer)))
tblSource.Columns.Add(New DataColumn("Year", GetType(Integer)))
tblSource.Columns.Add(New DataColumn("Month", GetType(Integer)))
For i As Int32 = 1 To 500000
Dim newRow = tblSource.NewRow
newRow("ID") = i
newRow("AccountNumber") = sampleAccountNumbers(rndAccNum.Next(0, sampleAccountNumbers.Count))
newRow("Year") = rndAccNum.Next(2005, 2012)
newRow("Month") = rndMonth.Next(1, 13)
tblSource.Rows.Add(newRow)
Next
End Sub
此示例在2005-2012期间随机使用4个静态AccountNumbers,其中包含500.000条记录。由于LINQ-to-DataSet完全在内存中运行,因此它仅在1.6秒内生成28个DataTable并克隆所有DataRows。