2011-08-13 66 views
1

我有一个包含AccountNumber,Year和Month的多列的DataTable。我将此表中的信息导出到Excel工作簿。由于这个表格可能会非常大,我必须检查表格中的记录数(因为Excel只能有65536行或类似的东西)如果原始表格足够小,我需要把所有记录如果一个工作表中的记录太多,我需要根据AccountNumber将记录分成多个工作表。此外,如果某个特定AccountNumber的记录太多,那么我需要将该AccountNumber分成多个工作表。基于年度如果一个特定的年份仍然有太多记录,然后我必须按月分裂他们从数据表中获取唯一记录的有效方法

例如:

如果我一共有500000条记录,我必须通过账户号码让它们分割:

工作表名称----记录数

  • 1111 ---- 150000
  • 2222 ---- 50000
  • 3333 ---- 100000

然后我需要根据年份将帐户1111和3333分成多个工作表。那么我有这样的事情:

表姓名----数纪录

  • 1111年至2010年---- 50000
  • 1111年至2011年---- 100000
  • 2222 ---- 50000
  • 3333-2010 ---- 50000
  • 3333-2011 ---- 50000

之后,由于1111年至2011年仍然过大,我不得不拆分一个基于一个月,终于给:

表姓名----号码记录

  • 1111年至2010年的--- - 50000
  • 1111-201105 ---- 30000
  • 1111-201106 ---- 30000
  • 1111-201107 ---- 40000
  • 2222 ---- 50000
  • 3333-2 010 ---- 50000
  • 3333-2011 ---- 50000

正被用于创建Excel文件的代码是被写了我公司的一个项目。为了简单起见,该函数接受DataTable并以Excel电子表格的格式将记录写出到DataTable中。关于如何在不再调用数据库的情况下做到这一点的任何想法?提前致谢。

+0

仅供参考,Excel 2007和更高版本可以有100万行。 –

+0

是的,但我们公司的一些个人电脑仍在使用2003 –

+0

似乎它可能会更容易,只是升级他们;) –

回答

0

您可以使用LINQ-to-DataSet分组相应的DataRows并将其添加到与更少的行超过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年期间以500.000记录随机4静态AccountNumbers。由于LINQ-to-DataSet完全在内存中工作,因此它仅生成28个DataTable并在1.6秒内克隆所有DataRows。

+0

谢谢这么多,我不得不改变一些小的细节,但这是一个很大的帮助。 –

0

您是否正在从数据库中专门为此操作提取数据?如果是这样,请使用SELECT DISTINCT并将数据库索引放在相关列上。这样,您不必担心它 - DBMS会为您过滤掉重复的行。所有剩下的事情就是遍历行并按照你的意愿对它们进行分组。

如果您正在使用分组行挣扎,你可以通过子句添加COUNT()来选择和组和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 
+0

不,Excel的一代 –

+0

Excel不是数据库Excel是正确的选择吗?考虑使用Access或csv文件 –

+0

它正在生成Excel报告供我们的推销员使用 –

相关问题