append questions in vba (1 Viewer)

jasn_78

Registered User.
Local time
Today, 14:57
Joined
Aug 1, 2001
Messages
214
Post your code for posterity?? And offcourse final analasys ;)

mailman ok so nearly final product on this code.

Code:
Public Function SALES(Journal As String)

FileCopy Journal, "C:\TFRS REPORTS\AJ1.CSV"

Name Journal As Left(Journal, 21) & "old"

DoCmd.TransferText acImportDelim, "aj1import", "tblAJLTEMP", "C:\TFRS REPORTS\AJ1.CSV"

Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim RsSales As DAO.Recordset
Dim RsAccounts As DAO.Recordset
Dim RsFunctions As DAO.Recordset
Dim RsItems As DAO.Recordset
Dim RsMembers As DAO.Recordset
Dim RsRounding As DAO.Recordset
Dim RsString As DAO.Recordset
Dim RsTables As DAO.Recordset
Dim RsTenders As DAO.Recordset
Dim RsGst As DAO.Recordset
'Dim RsQuery As DAO.Recordset
Dim qdf As DAO.QueryDef
Dim tbl As String
Dim strsql As String
Dim SALESID As Long
Dim delSQL As String
Dim qdel As DAO.QueryDef

tbl = "tblAJLTEMP"

Set db = CurrentDb
'Set qdf = db.QueryDefs("qryupdSALESTBL")
'Set qdel = db.QueryDefs("qrydeleteall")
Set rs = db.OpenRecordset("tblAJLTEMP", dbOpenTable)
Set RsSales = db.OpenRecordset("tblSales", dbOpenTable)
Set RsAccounts = db.OpenRecordset("tblACCOUNTTRX", dbOpenTable)
Set RsFunctions = db.OpenRecordset("tblFUNCTIONS", dbOpenTable)
Set RsItems = db.OpenRecordset("tblITEMSALES", dbOpenTable)
Set RsMembers = db.OpenRecordset("tblMEMBERTRX", dbOpenTable)
Set RsRounding = db.OpenRecordset("tblROUNDING", dbOpenTable)
Set RsString = db.OpenRecordset("tblString", dbOpenTable)
Set RsTables = db.OpenRecordset("tblTABLENUMBER", dbOpenTable)
Set RsTenders = db.OpenRecordset("tblTENDERS", dbOpenTable)
Set RsGst = db.OpenRecordset("tblGST", dbOpenTable)

'Set RsQuery = DB.OpenRecordset("SELECT * FROM tblSALESID ORDER BY SALESID", dbOpenDynaset)


Do While Not rs.EOF
    
    Select Case rs!Field1
    Case "H"
        RsSales.AddNew ' Start a new record
        RsSales!TRXTILLID = rs!Field2
        RsSales!TRXNUMBER = rs!Field3
        RsSales!TRXTIME = (rs!Field4 & ":" & rs!Field5)
        RsSales!TRXDATE = (rs!Field6 & "/" & rs!Field7 & "/" & rs!Field8)
        RsSales!TRXLOCATION = rs!Field9
        RsSales.Update ' Close the previous record)
    Case "P"
        txtprice = rs!Field2
    Case "C"
        txtCASHIER = rs!Field2
    Case "I"
        RsItems.AddNew
        RsItems!PLU = rs!Field2
        RsItems!QUANTITY = rs!Field3
        RsItems!AMOUNT = rs!Field4
        RsItems!pricelevel = (txtprice)
        RsItems!cashier = txtCASHIER
        RsItems!SALESID = DMax("tblSALES.SALESID", "tblSALES")
        RsItems.Update
    Case "D"
        RsTables.AddNew
        RsTables!TABLENUMBER = rs!Field2
        RsTables!SALESID = DMax("tblSALES.SALESID", "tblSALES")
        RsTables.Update
    Case "R"
        RsRounding.AddNew
        RsRounding!AMOUNT = rs!Field2
        RsRounding!SALESID = DMax("tblSALES.SALESID", "tblSALES")
        RsRounding.Update
    Case "T"
        Select Case rs!Field2
            Case Is = "65496"
            RsGst.AddNew
            RsGst!TenderType = rs!Field2
            RsGst!AMOUNT = rs!Field3
            RsGst!SALESID = DMax("tblSALES.SALESID", "tblSALES")
            RsGst.Update
            Case Else
            RsTenders.AddNew
            RsTenders!TenderType = rs!Field2
            RsTenders!AMOUNT = rs!Field3
            RsTenders!SALESID = DMax("tblSALES.SALESID", "tblSALES")
            RsTenders.Update
        End Select
    Case "A"
        RsAccounts.AddNew
        RsAccounts!ACCOUNT = rs!Field2
        RsAccounts!AMOUNT = rs!Field3
        RsAccounts!SALESID = DMax("tblSALES.SALESID", "tblSALES")
    Case "M"
        RsMembers.AddNew
        RsMembers!MEMBER = rs!Field2
        RsMembers!Points = rs!Field3
        RsMembers!SALESID = DMax("tblSALES.SALESID", "tblSALES")
        RsMembers.Update
    Case "S"
        RsString.AddNew
        RsString!PLU = rs!Field2
        RsString!INPUT = rs!Field3
        RsAccounts!SALESID = DMax("tblSALES.SALESID", "tblSALES")
        RsString.Update
    Case "L"
        RsFunctions.AddNew
        RsFunctions!KEYTYPE = rs!Field2
        RsFunctions!Function = rs!Field3
        RsFunctions!SALESID = DMax("tblSALES.SALESID", "tblSALES")
        RsFunctions.Update
    End Select
    
    rs.MoveNext
Loop

DoCmd.SetWarnings False

DoCmd.OpenQuery "qryDELTEMP"
DoCmd.Close

DoCmd.SetWarnings True



Kill "C:\TFRS REPORTS\aj1.csv"

End Function

so my only question is now the text file i am importing has dates from 2 days the reason for this is that the sales are from pubs where the trading of course runs past midnight, my question is should i leave the date as is in the text file or change it and just make my reports take the trading day end time into account

I am kinda guessing the 2nd way but just want to make sure and just am after opinions on my code

thanks
'
 

namliam

The Mailman - AWF VIP
Local time
Today, 06:57
Joined
Aug 11, 2003
Messages
11,695
Wow, talk about an old thread... a folllow up question after what 9 months??

I would make either two dates or leave the date as is. No way to revert back to the original date/time once you have fiddled with it. Keeping the data clean as you recieve it is usually advisable.
Offcourse you could just "adjust" the time to be "when < 10AM then part of previous day" kind of thing

Code:
        RsItems!SALESID = DMax("tblSALES.SALESID", "tblSALES")
        RsTables!SALESID = DMax("tblSALES.SALESID", "tblSALES")
        RsRounding!SALESID = DMax("tblSALES.SALESID", "tblSALES")
        RsGst!SALESID = DMax("tblSALES.SALESID", "tblSALES")
        RsTenders!SALESID = DMax("tblSALES.SALESID", "tblSALES")
        RsAccounts!SALESID = DMax("tblSALES.SALESID", "tblSALES")
        RsMembers!SALESID = DMax("tblSALES.SALESID", "tblSALES")
        RsAccounts!SALESID = DMax("tblSALES.SALESID", "tblSALES")
        RsFunctions!SALESID = DMax("tblSALES.SALESID", "tblSALES")
Wow you are doing 9 times the same thing, why??
Why not store this into a variable so you can retrieve it straight from memory??

You dont even need to DMax this, as basicaly you want the most recent sale that you added earlier on...
SomeVariable = rsSales!SalesID
Inserted prior to
RsSales.Update ' Close the previous record)
when adding the record will store the SalesID, which you can then add to your other tables.

One final peace of 'advice'
RsSales!TRXDATE = (rs!Field6 & "/" & rs!Field7 & "/" & rs!Field8)
Doing an impicit conversion like this is not advicable... this can go wrong in so many ways.
1) I hope you used MM/DD/YYYY format
2) Dateserial ( YYYY,MM,DD )
will allways go right and is the only 'proper' way to do this

Further more you are not using date/time as it is supposed to be. I presume both TRXTIME and TRXDATE are date(and time) fields...
Instead of having seperate fields for the date and time, make one field
TRXDATETIME and put both values in there.
Unless offcourse you have a specific (very good) reason to split this you should really store this information in one field.

Happy coding
 

jasn_78

Registered User.
Local time
Today, 14:57
Joined
Aug 1, 2001
Messages
214
namliam: now i know this is once again opening an old thread but figure its on this same code so better than asking in a new thread. Everything is working pretty well except seems to be running a bit slow on text files that are over 500kb in size, is there any thing else i can do to improve it I have included current code of where it is all at, also am I ok updating tables the way I am or should i be writing sql commands to add them?

Code:
Option Compare Database
Public Function SALES(Journal As String)
'this function imports a specified aj1 into a journal.gdb database

Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim RsSales As DAO.Recordset
Dim RsAccounts As DAO.Recordset
Dim RsFunctions As DAO.Recordset
Dim RsItems As DAO.Recordset
Dim RsMembers As DAO.Recordset
Dim RsRounding As DAO.Recordset
Dim RsString As DAO.Recordset
Dim RsTables As DAO.Recordset
Dim RsTenders As DAO.Recordset
Dim RsGst As DAO.Recordset
Dim qdf As DAO.QueryDef
Dim TBL As String
Dim strsql As String
Dim salesid As Long
Dim delSQL As String
Dim qdel As DAO.QueryDef
Dim TIMEDATE As String
Dim i As Variant
Dim stringtoextract As String
Dim recordnumber As Long
Dim totalrecords As Long

'set recordsets for journal.gdb
Set db = CodeDb
Set rs = db.OpenRecordset("tblAJLTEMP", dbOpenTable)
Set RsSales = db.OpenRecordset("TBLSALES") ', dbOpenTable)
Set RsAccounts = db.OpenRecordset("TBLACCOUNTTRX") ', dbOpenTable)
Set RsFunctions = db.OpenRecordset("TBLFUNCTIONS") ', dbOpenTable)
Set RsItems = db.OpenRecordset("TBLITEMSALES") ', dbOpenTable)
Set RsMembers = db.OpenRecordset("TBLMEMBERTRX") ', dbOpenTable)
Set RsRounding = db.OpenRecordset("TBLROUNDING") ', dbOpenTable)
Set RsString = db.OpenRecordset("TBLString") ', dbOpenTable)
Set RsTables = db.OpenRecordset("TBLTABLENUMBER") ', dbOpenTable)
Set RsTenders = db.OpenRecordset("TBLTENDERS") ', dbOpenTable)
Set RsGst = db.OpenRecordset("TBLGST") ', dbOpenTable)

i = InStrRev(Journal, ".", -1)

If Not IsNull(i) Then
    If i > 0 Then
    stringtoextract = Left(Journal, i)
    End If
End If

FileCopy Journal, CurrentProject.path & "\AJ1.CSV"

'   The file that contains the data to be copied over
    Open Journal For Input As #2

'   The file where the data will be appended
    Open stringtoextract & "BJL" For Append As #1

'   Loop through the data in file number 2 (#2) ...
    Do Until EOF(2)
        Line Input #2, Data

'       ... and append (write) the data into file number 1 (#1)
        Print #1, Data
    Loop

'   Close the files
    Close #2
    Close #1

'Name Journal As stringtoextract & "BJL"

Kill Journal

TBL = "TBLAJLTEMP"

DoCmd.TransferText acImportDelim, "aj1import", "TBLAJLTEMP", CurrentProject.path & "\AJ1.CSV"


'loop through temporary table and import into correct table
'the below fields and the meanings of each letter can be found in the ajl configuration manual as a pdf
'DoCmd.GoToRecord acDataTable, "TBLAJLTEMP", acFirst

rs.MoveLast
totalrecords = rs.RecordCount
recordnumber = 0

rs.MoveFirst

Do While Not rs.EOF
Forms!frmeod!progressEOD.SetFocus

Forms!frmeod!progressEOD.VALUE = recordnumber / totalrecords * 100


Select Case rs!field1
    Case "H"
        RsSales.AddNew ' Start a new record
        RsSales!TRXTILLID = rs!FIELD2
        RsSales!TRXNUMBER = rs!Field3
        TIMEDATE = (rs!Field8 & "-" & rs!Field7 & "-" & rs!Field6) & " " & (rs!FIELD4 & ":" & rs!FIELD5)
        RsSales!TRXTIMEDATE = TIMEDATE
        RsSales!TRXLOCATION = rs!FIELD9
        RsSales.Update ' Close the previous record)
        salesid = DMax("tblSALES.SALESID", "tblSALES")
    Case "P"
        txtprice = rs!FIELD2
    Case "C"
        txtCASHIER = rs!FIELD2
    Case "I"
        RsItems.AddNew
        RsItems!PLU = rs!FIELD2
        RsItems!QUANTITY = rs!Field3
        RsItems!AMOUNT = rs!FIELD4
        RsItems!PRICELEVEL = (txtprice)
        RsItems!cashier = txtCASHIER
        RsItems!salesid = salesid
        RsItems.Update
    Case "D"
        RsTables.AddNew
        RsTables!TABLENUMBER = rs!FIELD2
        RsTables!salesid = salesid
        RsTables.Update
    Case "R"
        RsRounding.AddNew
        RsRounding!AMOUNT = rs!FIELD2
        RsRounding!salesid = salesid
        RsRounding.Update
    Case "T"
        Select Case rs!FIELD2
            Case Is = "65496"
            RsGst.AddNew
            RsGst!TenderType = rs!FIELD2
            RsGst!AMOUNT = rs!Field3
            RsGst!salesid = salesid
            RsGst.Update
            Case Else
            RsTenders.AddNew
            RsTenders!TenderType = rs!FIELD2
            RsTenders!AMOUNT = rs!Field3
            RsTenders!salesid = salesid
            RsTenders.Update
        End Select
    Case "A"
        RsAccounts.AddNew
        RsAccounts!ACCOUNT = rs!FIELD2
        RsAccounts!AMOUNT = rs!Field3
        RsAccounts!salesid = salesid
        RsAccounts.Update
        RsTenders.AddNew
        RsTenders!TenderType = 1001
        RsTenders!AMOUNT = rs!Field3
        RsTenders!salesid = salesid
        RsTenders.Update
    Case "M"
        RsMembers.AddNew
        RsMembers!MEMBER = rs!FIELD2
        RsMembers!Point = rs!Field3
        RsMembers!salesid = salesid
        RsMembers.Update
    Case "S"
        RsString.AddNew
        RsString!PLU = rs!FIELD2
        RsString!Input = rs!Field3
        RsString!salesid = salesid
        RsString.Update
    Case "L"
        RsFunctions.AddNew
        RsFunctions!KEYTYPE = rs!FIELD2
        RsFunctions!FunctionS = rs!Field3
        RsFunctions!salesid = salesid
        RsFunctions.Update
    End Select
rs.MoveNext
recordnumber = recordnumber + 1

Loop



DoCmd.SetWarnings False
'delete temporary table of sales information
DoCmd.OpenQuery "qryDELTEMP"
'DoCmd.Close

DoCmd.SetWarnings True
'delete old aj1.csv
Kill CurrentProject.path & "\aj1.csv"

MsgBox "Sales Read In"

End Function
 

namliam

The Mailman - AWF VIP
Local time
Today, 06:57
Joined
Aug 11, 2003
Messages
11,695
Keeping a progress % on screen is a drain on resources! A serious drain...
Forms!frmeod!progressEOD.SetFocus
Forms!frmeod!progressEOD.VALUE = recordnumber / totalrecords * 100

Not updating every record but every 10 records or every say 5% or so... should improve your performance considerably. Also once progressEOD has focus, no need to set it again I think?
The less you display progress the better preformance... Simply make sure to display 100% at the end before displaying "Done" or else users might question your database if the % says 95% but the display says "done"


Why make a 1:1 copy twice??
Code:
FileCopy Journal, CurrentProject.path & "\AJ1.CSV"

'   The file that contains the data to be copied over
    Open Journal For Input As #2

'   The file where the data will be appended
    Open stringtoextract & "BJL" For Append As #1

'   Loop through the data in file number 2 (#2) ...
    Do Until EOF(2)
        Line Input #2, Data

'       ... and append (write) the data into file number 1 (#1)
        Print #1, Data
    Loop

'   Close the files
    Close #2
    Close #1
I dont see the point for 2 full copies?

More of a formatting thing...
Please indent your code 'properly'
Code:
Do While Not rs.EOF
Forms!frmeod!progressEOD.SetFocus

Forms!frmeod!progressEOD.VALUE = recordnumber / totalrecords * 100
...

        Select Case rs!FIELD2
            Case Is = "65496"
            RsGst.AddNew
            RsGst!TenderType = rs!FIELD2
            RsGst!AMOUNT = rs!Field3
            RsGst!salesid = salesid
            RsGst.Update
            Case Else
            RsTenders.AddNew
            RsTenders!TenderType = rs!FIELD2
            RsTenders!AMOUNT = rs!Field3
            RsTenders!salesid = salesid
            RsTenders.Update
        End Select
Above is not indented properly...


Code:
        TIMEDATE = (rs!Field8 & "-" & rs!Field7 & "-" & rs!Field6) & " " & (rs!FIELD4 & ":" & rs!FIELD5)
        RsSales!TRXTIMEDATE = TIMEDATE
Assuming TRXTIMEDATE is a date/time field, doing implicit conversions is a bad bad bad thing!
Instead do explicit conversions to make sure Access doesnt mess up your date(s).
Use the Dateserial and TimeSerial functions to compilate your date/time field.
Dateserial (Year,Month,Day) + TimeSerial (hour, Minute, Seconds)

Dmax... *ouch*
Code:
       salesid = DMax("tblSALES.SALESID", "tblSALES")
DMax is slow to the Ultimate! In particular since you dont need it... Your PK (SalesID) is created at the moment of ".AddNew"
Simply add before ".Update"
salesid = RsSales!SALESID
That will fetch it too, and save you a BUNDLE on processing time...


Other than that, some import process into multiple tables is just going to take time... Barring the (possible) conversion from straight VBA code into SQL statements
 

jasn_78

Registered User.
Local time
Today, 14:57
Joined
Aug 1, 2001
Messages
214
Thanks mate will have a look at all your suggestions, couple of questions.

1. When you say update every ten records or so at a time the reason I am using the dmax function is to make sure that the salesid I have in tblSALES is the same used in my other tables when inserting the data in those, wont by updating more than one record at a time not allow me to do this?

2. The reason for the filecopy code is to append to the "BJL" file when it already exists as the user may have already called in sales once for that day, any other suggestions?


Thanks alot :)
 

namliam

The Mailman - AWF VIP
Local time
Today, 06:57
Joined
Aug 11, 2003
Messages
11,695
1)
Updating your progress is completely seperate from updating your primary key...
The primary key you NEED every time... Updating the progress... perhaps not...
I.e. if the average file takes on average 10 seconds to process, for 100 records...
I would probably go with an update every 20 records (2 seconds).
The trick with the progress is give the user the idea that your App is doing something, with the app beeing hard at work to update the user.
The main point for the App is to do its thing... User is secondary...

2)
If its needed its needed... just looks strange, perhaps you code needs a comment or two to enlighten any 'stranger' that might look at your code for what ever reason (perhaps the guy that gets your job when you leave -if ever-, or yourself in 5 years from now when you have no clue what you did)
 

jasn_78

Registered User.
Local time
Today, 14:57
Joined
Aug 1, 2001
Messages
214
thanks mailman, sorry for all the questions just trying to follow everything :) the only other question i have atm is when you say change the date to a dateserial value what will happen if i change from access at a later point as im trying to learn .net as well atm so cant see me sticking with access for the rest of the time will this have an affect on being able to read that value or if the actual programmer at work who uses delphi needs to access it (which is doubtful) but might would he be able to under a dateserial value?

Thanks
 

namliam

The Mailman - AWF VIP
Local time
Today, 06:57
Joined
Aug 11, 2003
Messages
11,695
In (most) other languages what you are doing is IMPOSSIBLE and will generate an error.
You are sticking a string value into a date field... IMPOSSIBLE.
Access is so kind as to auto convert it for you, to make it work. But access can make errors in thinking for you... Which is why most languages/enviroments demand you determain how to convert a string to a date (or to a number, or a number to a string etc....) that way it is doing what YOU want, not what the system thinks it should do determained by semi-random things like your Regional settings!

BTW
1) There is a perfect living to be made using access.
A lot of resistance against Access solutions in the "general population" of managers, yet for some reason my solutions always come in ON time ON budget. While the (better?) .Net/datawarehouse/etc solutions are neither ever...
A quick solid 99% fix in access beats out a 1% fix in any other situation always, dont frown on the power of this tool
2) .Net
Ooooooooooh buzz word!
3) Basics
A lot of this comes down to basics, if you get your foundation wrong... Sooner or later the house is going to come down! Get the basics right... and your halfway there.
 

Users who are viewing this thread

Top Bottom