奇怪的Excel格式

最近,我们公司聘请了一个新的合作社,负责提交报告。 该报告查询数据库并返回一个结果集并从那里开始创build电子表格。 根据select的天数,生成不同数量的报告,但我不认为这是相关的问题。 基本上它运行的报告,并通过结果集循环,但在某个点上继续循环,直到它停在65536。 例如,如果结果集包含74条logging,则前74行将正常显示(格式化为黄色),而之后的所有内容也将被格式化为黄色,尽pipe它应该单独保留。 我inheritance了这个代码,因为我是一个新的合作社。 显然,这只有在“换岗”时才会发生(新合作社必须运行报告)

DoCmd.SetWarnings False DoCmd.OpenQuery ("DailySummaryQueryMain") strSQL = "SELECT * FROM DailySummaryMain" Set rs = CurrentDb.OpenRecordset(strSQL) DoCmd.Echo True, "Running first Report" If Not rs.EOF Then rs.MoveFirst Do While Not rs.EOF And Not rs.BOF xlapp.Range("A" & i).Value = rs.Fields(0).Value xlapp.Range("B" & i).Value = rs.Fields(1).Value xlapp.Range("C" & i).Value = rs.Fields(2).Value Set rs2 = CurrentDb.OpenRecordset("SELECT dbo_StatusType.StatusTypeID, dbo_StatusType.Name FROM dbo_StatusType WHERE (((dbo_StatusType.StatusTypeID)=" & rs.Fields(3) & "))") rs2.MoveFirst xlapp.Range("D" & i).Value = rs2.Fields(1).Value xlapp.Range("E" & i).Value = rs.Fields(4).Value xlapp.Range("F" & i).Value = rs.Fields(5).Value xlapp.Range("G" & i).Value = rs.Fields(6).Value 'count number of outages that start and end on same day If Format(xlapp.Range("F" & i).Value, "mm/dd/yyyy") = Format(xlapp.Range("G" & i).Value, "mm/dd/yyyy") Then dayCount = dayCount + 1 End If xlapp.Range("H" & i).Value = rs.Fields(7).Value xlapp.Range("I" & i).Value = rs.Fields(8).Value xlapp.Range("J" & i).Value = rs.Fields(9).Value xlapp.Range("K" & i).Value = rs.Fields(10).Value xlapp.Range("L" & i).Value = rs.Fields(11).Value xlapp.Range("M" & i).Value = rs.Fields(12).Value xlapp.Range("N" & i).Value = rs.Fields(13).Value 'highlite recently modified rows If rs.Fields(14).Value = "Yes" Then xlapp.Range("A" & i & ":N" & i).Select With xlapp.Selection.Interior .ColorIndex = 36 .Pattern = xlSolid End With End If 'break apart by sector If CInt(rs.Fields(2).Value) = 1 Then row = row1 ElseIf CInt(rs.Fields(2).Value) = 2 Then row = row2 ElseIf CInt(rs.Fields(2).Value) = 3 Then row = row3 Else row = row4 End If xlapp.Worksheets(CInt(rs.Fields(2).Value) + 1).Activate xlapp.Range("A" & row).Value = rs.Fields(0).Value xlapp.Range("B" & row).Value = rs.Fields(1).Value xlapp.Range("C" & row).Value = rs.Fields(13).Value xlapp.Range("D" & row).Value = rs.Fields(4).Value xlapp.Range("E" & row).Value = rs.Fields(5).Value xlapp.Range("F" & row).Value = rs.Fields(6).Value xlapp.Range("G" & row).Value = rs.Fields(7).Value xlapp.Range("H" & row).Value = rs.Fields(8).Value xlapp.Range("I" & row).Value = rs.Fields(9).Value xlapp.Range("J" & row).Value = rs.Fields(10).Value xlapp.Range("K" & row).Value = "" xlapp.Range("L" & row).Value = rs.Fields(11).Value xlapp.Range("M" & row).Value = rs.Fields(13).Value If CInt(rs.Fields(2).Value) = 1 Then row1 = row1 + 1 ElseIf CInt(rs.Fields(2).Value) = 2 Then row2 = row2 + 1 ElseIf CInt(rs.Fields(2).Value) = 3 Then row3 = row3 + 1 Else row4 = row4 + 1 End If 'activate main summary sheet for next outage xlapp.Worksheets(1).Activate i = i + 1 rs.MoveNext Loop` 

另外我应该注意到,这一切都发生在一个访问数据库,其中有从SQL链接表。 该查询是非常缓慢的运行,我相信是使用的意见,但多数民众赞成在这里或那里。 所有你必须知道的是试图debugging需要大量的时间,因为不得不等待logging集返回。 我的猜测是,它不检查结果集是否是空的正确。 有没有一种方法,我可以检查,看它们是否是一个值是rs.Fields(0)并基于它可能吗? 这是ID列,应该始终有一个值。 我想知道为什么rs.EOF不捕捉这个。

几个意见,其中没有一个是对你的问题的答案,但可能会指出你在正确的方向:

更改空logging集的testing/何时停止循环。

replace此代码:

  If Not rs.EOF Then rs.MoveFirst Do While Not rs.EOF And Not rs.BOF [...] rs.MoveNext 

…有了这个:

  If rs.RecordCount<> 0 rs.MoveFirst Do While Not rs.EOF [...] rs.MoveNext 

改变第二个logging集的使用方式。

不要为每一行打开一次,针对该行进行过滤,但是不要过滤打开它,并按以前过滤的值进行sorting,然后使用FindFirst对其进行导航:

  Set rs = CurrentDb.OpenRecordset("SELECT * FROM DailySummaryMain") Set rs2 = CurrentDb.OpenRecordset("SELECT dbo_StatusType.StatusTypeID, dbo_StatusType.Name FROM dbo_StatusType ORDER BY dbo_StatusType.StatusTypeID") [...] rs2.FindFirst "[StatusTypeID]=" & rs.Fields(3) 

…或者使第二个logging集过时。

更好的是,看起来这里有一个匹配的值,因为rs2从来没有被导航过第一个匹配,所以为什么不看看是否可以改变保存的QueryDef“DailySummaryMain”来join到dbo_StatusType中,以便值在那里单个logging集? 那么你根本就不需要rs2。

通过序号来引用字段通常是不明智的。

通过在SELECT语句的结尾以外的任何位置添加一个新的字段到源SELECT语句,可以很容易地完成您的例程。 因此,将序号更改为实际字段名称,以使rs(0)变为rs(“NameOfFirstField”)。

使用SELECT CASE而不是链接的If / Then / ElseIf / Else。

更改此代码:

  If CInt(rs.Fields(2).Value) = 1 Then row = row1 ElseIf CInt(rs.Fields(2).Value) = 2 Then row = row2 ElseIf CInt(rs.Fields(2).Value) = 3 Then row = row3 Else row = row4 End If 

对此:

  Select Case rs.Fields(2) Case 1 row = row1 Case 2 row = row2 Case 3 row = row3 Case 4 row = row4 End Select 

或者,因为除了一个案件都可以从价值构build,所以做到这一点:

  If rs.Fields(2) = 4 Then row = row4 Else row = Eval("row" & rs.Fields(2)) End If 

上下文不完全清楚(行和行N的含义是不明确的 – 他们的variables是某种types的对象?),所以也许最后不会工作(Eval()并不总是工作的情况下它似乎应该),所以我可能会去与SELECT CASE。

Excel可能需要.Value但Access不。

改变这个:

  xlapp.Range("A" & i).Value = rs.Fields(0).Value 

对此:

  xlapp.Range("A" & i).Value = rs.Fields(0) 

你也许不需要它在Excel的Excel方面。

65536是有意义的,因为它比可以存储在16位无符号整数中的最大值多1。所以有些东西在某处溢出。

这不会是一个VBA整数,因为他们是签名的,但我仍然会用CLng()replaceCInt() ,并确保计数器variables像i一样被声明为long

你有没有运行它的error handling禁用,看是否有任何错误提出?

至于debugging,您可以交换到ADO,运行一次,并将结果保存到磁盘( RS.Save ),然后RS.Open . RS.Open该文件进行后续运行。