G
George Nicholson
I've run into a problem that I don't quite understand, so at a loss to a
solution.
SETUP:
I have a mdb file which includes 2 tables: datOrderHeader * datOrderDetail.
I have weekly csv files that need to be imported into these tables. The 1st
35 values in the csv go into datOrderHeader. The remaining csv values go
into datOrderDetail in groups of 3 per record. i.e., values 36, 37, 38 make
one detail record. 39, 40, 41 (if they exist) make a second detail record
for that order, etc., etc. No limit to the number of detail records per
order (so no telling how long my longest csv record will be either and the
import wizard is useless unless your longest record is included in 1st 20 or
so records, which is why I'm doing it this way).
I have working code that prompts user for file location, opens the file,
reads a line, adds the data to my tables, reads next line, etc. and it works
fine.
HERE IS MY PROBLEM: I start with a compacted mdb of 354mb. I try to import a
csv file with 434k records and my code crashes at record 409k because the
mdb is now 2gb (Jet file size limit). That (incomplete) file compacts to
514mb.
What the *!#% is causing bloat of 1.5GB???? No temp tables. No field
modifications. No deletions of anything. Simply open a text file and add
records.
Here is most of the code I'm using (sorry for length). There are a couple of
"GetYadayada" functions which are all very straightforward "evaluate &
return" functions. One of them has a Dlookup, otherwise they are all self
contained, so I seriously doubt they are causing any bloat.
*Any* insights into the bloat issue would be appreciated. I'd love to be
able to eliminate as much the bloat as I can so I can import complete files
in one pass.
TIA,
****************************
Public Function ReadCSVData(Optional strFilename As String) As Boolean
' Purpose: read comma-delimited data from text file and store in Access
tables
' In: name of text file containing information
' Out:
On Error GoTo ErrHandler
Dim db As DAO.Database
Dim rsHeader As DAO.Recordset
Dim rsDetail As DAO.Recordset
Dim str As String
Dim strArray() As String
Dim intE As Integer 'E for Element(s) of Array
Dim strDescription As String
Dim iOrdCount As Long
Dim iBatchLineItems As Long
Dim lngOrderID As Long
Dim iDetailFields As Long
Dim varSysCmd As Variant
Dim dtmStart As Date
Dim strElapsed As String
Dim iLineItems As Long
Dim iTotalItems As Long
ReadCSVData = False
If Len(strFilename) = 0 Then
strFilename = CStr(CommonFileOpenSave)
If Len(Dir(strFilename)) = 0 Then
MsgBox "Cancelling: User canceled or file does not exist"
GoTo ExitHere
End If
End If
Do Until Len(strDescription) > 0
strDescription = InputBox("Enter the DataBatchID # for this data or
type 'CANCEL'.")
Select Case strDescription
Case ""
'Do nothing. Loop
Case "Cancel", "CANCEL"
GoTo ExitHere
Case Else
If IsNumeric(strDescription) Then
'Continue
Else
' invalid entry
strDescription = ""
End If
End Select
Loop
dtmStart = Now()
Set db = CurrentDb
Set rsHeader = db.OpenRecordset("datOrderSummary")
Set rsDetail = db.OpenRecordset("datOrderDetail")
Open strFilename For Input As #1
Do While Not EOF(1)
Line Input #1, str
strArray = Split(str, ",", -1)
iLineItems = 0
iTotalItems = 0
If UBound(strArray) < 35 Then
MsgBox "Logic Error in code for 'ReadCSVData'. Record is shorter
than expected."
GoTo NextRecord
End If
With rsHeader
.AddNew
iOrdCount = iOrdCount + 1
For intE = LBound(strArray) To 35
Select Case intE + 1
' The + 1 is strictly for convenience and ease of
debugging/reading,
' so the case statements correspond to the documented
field numbering.
Case 1
!StoreNo = CLng(strArray(intE))
Case 2
!TCDate = CDate(strArray(intE))
Case 3
!TCTime = CDate(strArray(intE))
Case 4
!StorewideTCNum = CLng(strArray(intE))
Case 5
!KSNo = CInt(strArray(intE))
Case 6
!KSOrdNo = CLng(strArray(intE))
Case 7
!NetAmount = CCur(strArray(intE))
Case 8
!Tax = CCur(strArray(intE))
Case 9
!NonProductAmt = CCur(strArray(intE))
Case 10
!DiscAmount = CCur(strArray(intE))
Case 11
!GCertRedeemedAmt = CCur(strArray(intE))
Case 12
!GCardRedeemedAmt = CCur(strArray(intE))
Case 13
!GCardRedeemedQty = CInt(strArray(intE))
Case 14
!GCertSoldAmt = CCur(strArray(intE))
Case 15
!GCardSoldAmt = CCur(strArray(intE))
Case 16
!GCardSoldQty = CInt(strArray(intE))
Case 17
!Tendered = CCur(strArray(intE))
Case 18
!PaymentType = CByte(strArray(intE))
Case 19
!DTFlag = CByte(strArray(intE))
If !DTFlag = 0 Then !DTFlag = 2
Case 20
!CarryOutFlag = CByte(strArray(intE))
Case 21
!RefundFlag = CByte(strArray(intE))
Case 22
!EmpDiscFlag = CByte(strArray(intE))
Case 23
!MgrDiscFlag = CByte(strArray(intE))
Case 24
!OtherDiscFlag = CByte(strArray(intE))
Case 25
!OverringFlag = CByte(strArray(intE))
Case 26
!OtherReceiptFlag = CByte(strArray(intE))
Case 27
![Stored/HeldFlag] = CByte(strArray(intE))
Case 28
!KioskFlag = CByte(strArray(intE))
Case 29
!KVSPrepLine = CByte(strArray(intE))
Case 30
!TotalServiceTime = CLng(strArray(intE))
Case 31
!OrderTime = CLng(strArray(intE))
Case 32
!LineOrAssemblyTime = CLng(strArray(intE))
Case 33
!WindowOrCashierTime = CLng(strArray(intE))
Case 34
!ServeOrStorageTime = CLng(strArray(intE))
Case 35
!HoldOrGlobalTime = CLng(strArray(intE))
Case 36
!POSItemCount = CInt(strArray(intE))
Case Else
MsgBox "Error: Logic error in code 'ReadCSVData'.
Incorrect Header field numbering."
End Select
Next intE
lngOrderID = !OrderID
!AddedOn = Now()
!DataBatchID = CLng(strDescription)
!Weekending = GetWeekending(!TCDate)
!Weekpart = GetWeekPart(!TCDate)
!Daypart = GetDayPart(!TCDate, !TCTime)
!QHour = GetQHour(!TCTime)
.Update
End With
If UBound(strArray) = 35 Then
' No detail records apparently
GoTo NextRecord
End If
iDetailFields = UBound(strArray) - 35
If iDetailFields Mod 3 <> 0 Then
MsgBox "Error: Logic error in code 'ReadCSVData'. Incorrect
LineItem field count."
End If
With rsDetail
For intE = 36 To UBound(strArray)
Select Case intE Mod 3
Case 0
'MenuItemID
.AddNew
iBatchLineItems = iBatchLineItems + 1
!Referenced = False
!OriginalSequence = CByte((intE - 33) / 3)
!OrderID = lngOrderID
!MenuItemID = Format(strArray(intE), "00000")
Case 1
'QtyServed
!QtyServed = CInt(strArray(intE))
If !QtyServed <> 0 Then
iLineItems = iLineItems + 1
iTotalItems = iTotalItems + !QtyServed
End If
Case 2
'QtyPromo
!QtyPromo = CInt(strArray(intE))
.Update
Case Else
MsgBox "Error: Logic error in code 'ReadCSVData'.
Incorrect Detail field numbering."
End Select
Next intE
End With
With rsHeader
.Bookmark = .LastModified
.Edit
!LineItems = iLineItems
!TotalItems = iTotalItems
!Complexity = GetComplexity(iLineItems, iTotalItems)
.Update
End With
If iOrdCount Mod 1000 = 0 Then
varSysCmd = SysCmd(acSysCmdSetStatus, Format(iOrdCount,
"#,###,###") & " orders and " & Format(iBatchLineItems, "#,###,###") & "
line items have been processed...")
DoEvents
End If
NextRecord:
Loop
strElapsed = Format(Now() - dtmStart, "hh:nn:ss")
MsgBox "File processed in " & strElapsed & vbCrLf & vbCrLf & _
Format(iOrdCount, "#,###,###") & " orders added." & vbCrLf & _
Format(iBatchLineItems, "#,###,###") & " line items added."
ReadCSVData = True
ExitHere:
On Error Resume Next
varSysCmd = SysCmd(acSysCmdSetStatus, " ")
Close #1
Set rsDetail = Nothing
Set rsHeader = Nothing
Set db = Nothing
Exit Function
ErrHandler:
Select Case Err
Case Else
MsgBox "UNLOGGED ERROR: " & vbCrLf & vbCrLf & Err.Number & " - "
& Err.Description
Resume ExitHere
End Select
End Function
solution.
SETUP:
I have a mdb file which includes 2 tables: datOrderHeader * datOrderDetail.
I have weekly csv files that need to be imported into these tables. The 1st
35 values in the csv go into datOrderHeader. The remaining csv values go
into datOrderDetail in groups of 3 per record. i.e., values 36, 37, 38 make
one detail record. 39, 40, 41 (if they exist) make a second detail record
for that order, etc., etc. No limit to the number of detail records per
order (so no telling how long my longest csv record will be either and the
import wizard is useless unless your longest record is included in 1st 20 or
so records, which is why I'm doing it this way).
I have working code that prompts user for file location, opens the file,
reads a line, adds the data to my tables, reads next line, etc. and it works
fine.
HERE IS MY PROBLEM: I start with a compacted mdb of 354mb. I try to import a
csv file with 434k records and my code crashes at record 409k because the
mdb is now 2gb (Jet file size limit). That (incomplete) file compacts to
514mb.
What the *!#% is causing bloat of 1.5GB???? No temp tables. No field
modifications. No deletions of anything. Simply open a text file and add
records.
Here is most of the code I'm using (sorry for length). There are a couple of
"GetYadayada" functions which are all very straightforward "evaluate &
return" functions. One of them has a Dlookup, otherwise they are all self
contained, so I seriously doubt they are causing any bloat.
*Any* insights into the bloat issue would be appreciated. I'd love to be
able to eliminate as much the bloat as I can so I can import complete files
in one pass.
TIA,
****************************
Public Function ReadCSVData(Optional strFilename As String) As Boolean
' Purpose: read comma-delimited data from text file and store in Access
tables
' In: name of text file containing information
' Out:
On Error GoTo ErrHandler
Dim db As DAO.Database
Dim rsHeader As DAO.Recordset
Dim rsDetail As DAO.Recordset
Dim str As String
Dim strArray() As String
Dim intE As Integer 'E for Element(s) of Array
Dim strDescription As String
Dim iOrdCount As Long
Dim iBatchLineItems As Long
Dim lngOrderID As Long
Dim iDetailFields As Long
Dim varSysCmd As Variant
Dim dtmStart As Date
Dim strElapsed As String
Dim iLineItems As Long
Dim iTotalItems As Long
ReadCSVData = False
If Len(strFilename) = 0 Then
strFilename = CStr(CommonFileOpenSave)
If Len(Dir(strFilename)) = 0 Then
MsgBox "Cancelling: User canceled or file does not exist"
GoTo ExitHere
End If
End If
Do Until Len(strDescription) > 0
strDescription = InputBox("Enter the DataBatchID # for this data or
type 'CANCEL'.")
Select Case strDescription
Case ""
'Do nothing. Loop
Case "Cancel", "CANCEL"
GoTo ExitHere
Case Else
If IsNumeric(strDescription) Then
'Continue
Else
' invalid entry
strDescription = ""
End If
End Select
Loop
dtmStart = Now()
Set db = CurrentDb
Set rsHeader = db.OpenRecordset("datOrderSummary")
Set rsDetail = db.OpenRecordset("datOrderDetail")
Open strFilename For Input As #1
Do While Not EOF(1)
Line Input #1, str
strArray = Split(str, ",", -1)
iLineItems = 0
iTotalItems = 0
If UBound(strArray) < 35 Then
MsgBox "Logic Error in code for 'ReadCSVData'. Record is shorter
than expected."
GoTo NextRecord
End If
With rsHeader
.AddNew
iOrdCount = iOrdCount + 1
For intE = LBound(strArray) To 35
Select Case intE + 1
' The + 1 is strictly for convenience and ease of
debugging/reading,
' so the case statements correspond to the documented
field numbering.
Case 1
!StoreNo = CLng(strArray(intE))
Case 2
!TCDate = CDate(strArray(intE))
Case 3
!TCTime = CDate(strArray(intE))
Case 4
!StorewideTCNum = CLng(strArray(intE))
Case 5
!KSNo = CInt(strArray(intE))
Case 6
!KSOrdNo = CLng(strArray(intE))
Case 7
!NetAmount = CCur(strArray(intE))
Case 8
!Tax = CCur(strArray(intE))
Case 9
!NonProductAmt = CCur(strArray(intE))
Case 10
!DiscAmount = CCur(strArray(intE))
Case 11
!GCertRedeemedAmt = CCur(strArray(intE))
Case 12
!GCardRedeemedAmt = CCur(strArray(intE))
Case 13
!GCardRedeemedQty = CInt(strArray(intE))
Case 14
!GCertSoldAmt = CCur(strArray(intE))
Case 15
!GCardSoldAmt = CCur(strArray(intE))
Case 16
!GCardSoldQty = CInt(strArray(intE))
Case 17
!Tendered = CCur(strArray(intE))
Case 18
!PaymentType = CByte(strArray(intE))
Case 19
!DTFlag = CByte(strArray(intE))
If !DTFlag = 0 Then !DTFlag = 2
Case 20
!CarryOutFlag = CByte(strArray(intE))
Case 21
!RefundFlag = CByte(strArray(intE))
Case 22
!EmpDiscFlag = CByte(strArray(intE))
Case 23
!MgrDiscFlag = CByte(strArray(intE))
Case 24
!OtherDiscFlag = CByte(strArray(intE))
Case 25
!OverringFlag = CByte(strArray(intE))
Case 26
!OtherReceiptFlag = CByte(strArray(intE))
Case 27
![Stored/HeldFlag] = CByte(strArray(intE))
Case 28
!KioskFlag = CByte(strArray(intE))
Case 29
!KVSPrepLine = CByte(strArray(intE))
Case 30
!TotalServiceTime = CLng(strArray(intE))
Case 31
!OrderTime = CLng(strArray(intE))
Case 32
!LineOrAssemblyTime = CLng(strArray(intE))
Case 33
!WindowOrCashierTime = CLng(strArray(intE))
Case 34
!ServeOrStorageTime = CLng(strArray(intE))
Case 35
!HoldOrGlobalTime = CLng(strArray(intE))
Case 36
!POSItemCount = CInt(strArray(intE))
Case Else
MsgBox "Error: Logic error in code 'ReadCSVData'.
Incorrect Header field numbering."
End Select
Next intE
lngOrderID = !OrderID
!AddedOn = Now()
!DataBatchID = CLng(strDescription)
!Weekending = GetWeekending(!TCDate)
!Weekpart = GetWeekPart(!TCDate)
!Daypart = GetDayPart(!TCDate, !TCTime)
!QHour = GetQHour(!TCTime)
.Update
End With
If UBound(strArray) = 35 Then
' No detail records apparently
GoTo NextRecord
End If
iDetailFields = UBound(strArray) - 35
If iDetailFields Mod 3 <> 0 Then
MsgBox "Error: Logic error in code 'ReadCSVData'. Incorrect
LineItem field count."
End If
With rsDetail
For intE = 36 To UBound(strArray)
Select Case intE Mod 3
Case 0
'MenuItemID
.AddNew
iBatchLineItems = iBatchLineItems + 1
!Referenced = False
!OriginalSequence = CByte((intE - 33) / 3)
!OrderID = lngOrderID
!MenuItemID = Format(strArray(intE), "00000")
Case 1
'QtyServed
!QtyServed = CInt(strArray(intE))
If !QtyServed <> 0 Then
iLineItems = iLineItems + 1
iTotalItems = iTotalItems + !QtyServed
End If
Case 2
'QtyPromo
!QtyPromo = CInt(strArray(intE))
.Update
Case Else
MsgBox "Error: Logic error in code 'ReadCSVData'.
Incorrect Detail field numbering."
End Select
Next intE
End With
With rsHeader
.Bookmark = .LastModified
.Edit
!LineItems = iLineItems
!TotalItems = iTotalItems
!Complexity = GetComplexity(iLineItems, iTotalItems)
.Update
End With
If iOrdCount Mod 1000 = 0 Then
varSysCmd = SysCmd(acSysCmdSetStatus, Format(iOrdCount,
"#,###,###") & " orders and " & Format(iBatchLineItems, "#,###,###") & "
line items have been processed...")
DoEvents
End If
NextRecord:
Loop
strElapsed = Format(Now() - dtmStart, "hh:nn:ss")
MsgBox "File processed in " & strElapsed & vbCrLf & vbCrLf & _
Format(iOrdCount, "#,###,###") & " orders added." & vbCrLf & _
Format(iBatchLineItems, "#,###,###") & " line items added."
ReadCSVData = True
ExitHere:
On Error Resume Next
varSysCmd = SysCmd(acSysCmdSetStatus, " ")
Close #1
Set rsDetail = Nothing
Set rsHeader = Nothing
Set db = Nothing
Exit Function
ErrHandler:
Select Case Err
Case Else
MsgBox "UNLOGGED ERROR: " & vbCrLf & vbCrLf & Err.Number & " - "
& Err.Description
Resume ExitHere
End Select
End Function