I want to loop through a folder and import all the files into Access.
This is my code:
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim fso, MyFile, FileName, TextLine
Dim TextArray()
Dim x As Double
Dim SQLString
Set fso = CreateObject("Scripting.FileSystemObject")
FileName = "C:\Users\ava\Desktop\TEST_IMPORT\1.txt"
Set MyFile = fso.OpenTextFile(FileName, ForReading)
Do While MyFile.AtEndOfStream <> True
ReDim Preserve TextArray(x)
TextLine = MyFile.ReadLine
TextArray(x) = TextLine
x = x + 1
Loop
MyFile.Close
SQLString = "INSERT INTO TEST_TAB (Layout, Anzahl_Etiketten, Anzahl_Verpackungseinheiten, Bezeichnung1, Selektionsnummer, Bezeichnung2, Barcode, LA_Nummer, RM_Nummer, Bezeichnung3, Teilenummer) VALUES ('" & TextArray(0) & "','" & TextArray(1) & "','" & TextArray(4) & "','" & TextArray(5) & "','" & TextArray(6) & "','" & TextArray(7) & "','" & TextArray(9) & "','" & TextArray(10) & "','" & TextArray(13) & "','" & TextArray(15) & "','" & TextArray(19) & "');"
DoCmd.SetWarnings (WarningsOff)
DoCmd.RunSQL SQLString
DoCmd.SetWarnings (WarningsOn)
End Sub
The code imports a text file from my desktop (1.txt) then imports the data into my Access DB.
This works for my one File. (1.txt)
I found this link how to loop through a folder.
How do I implement that into my code?
im assuming you are reading every file with extension .txt in the folder C:\Users\ava\Desktop.
Try this...
Dim TextArray()
Dim x As Double
Dim SQLString
Set fso = CreateObject("Scripting.FileSystemObject")
strFolder= "C:\Users\ava\Desktop" 'sets folder
strFileName = Dir(strFolder & "\*.txt") 'grabs first txt file
Do While strFileName <> 0 'starts loop
FileName = strFileName 'set filename
Set MyFile = fso.OpenTextFile(FileName, ForReading)
'' Read from the file
Do While MyFile.AtEndOfStream <> True
ReDim Preserve TextArray(x)
TextLine = MyFile.ReadLine
TextArray(x) = TextLine
x = x + 1
Loop
MyFile.Close
SQLString = "INSERT INTO TEST_TAB (Layout, Anzahl_Etiketten, Anzahl_Verpackungseinheiten, Bezeichnung1, Selektionsnummer, Bezeichnung2, Barcode, LA_Nummer, RM_Nummer, Bezeichnung3, Teilenummer) VALUES ('" & TextArray(0) & "','" & TextArray(1) & "','" & TextArray(4) & "','" & TextArray(5) & "','" & TextArray(6) & "','" & TextArray(7) & "','" & TextArray(9) & "','" & TextArray(10) & "','" & TextArray(13) & "','" & TextArray(15) & "','" & TextArray(19) & "');"
DoCmd.SetWarnings (WarningsOff)
DoCmd.RunSQL SQLString
DoCmd.SetWarnings (WarningsOn)
strFileName = Dir 'Grabs next txt file
Loop
I'm not sure why you are using TextArray over and over and over, but consider doing it like this.
Option Compare Database
Private Sub Command0_Click()
Dim strPathFile As String, strFile As String, strPath As String
Dim strTable As String
Dim blnHasFieldNames As Boolean
' Change this next line to True if the first row in EXCEL worksheet
' has field names
blnHasFieldNames = True
' Replace C:\Documents\ with the real path to the folder that
' contains the EXCEL files
strPath = "C:\Users\rschuell\Desktop\test\"
' Replace tablename with the real name of the table into which
' the data are to be imported
strTable = "tablename"
strFile = Dir(strPath & "*.txt")
Do While Len(strFile) > 0
strPathFile = strPath & strFile
DoCmd.TransferText _
TransferType:=acImportDelim, _
TableName:=strTable, _
FileName:=strPathFile, _
HasFieldNames:=blnHasFieldNames
' Uncomment out the next code step if you want to delete the
' EXCEL file after it's been imported
' Kill strPathFile
strFile = Dir()
Loop
End Sub
Related
I've written a function to loop through an array of a custom object (C_Document). In the loop, if the document number does not already exist, it should insert a new record into the table tbl_docs. If the document does exist, it should update the appropriate record in the database.
Public Function updateDocuments(docs() As C_Document) As Double
Dim db As Object
Set db = Application.CurrentDb
Dim docIndex As Double
'Loop through all imported documents
For docIndex = 1 To UBound(docs)
Dim strSQL As String
Dim exists As Double
exists = DCount("docNo", "tbl_docs", "docNo = '" & docs(docIndex).getDocNo() & "'" > 0)
'Check if entry already exists
If (exists > 0) Then
'docNo entry already exists - update
strSQL = "UPDATE tbl_docs SET " & _
"docReviewStatus = " & docs(docIndex).getDocStatus() & "," & _
"docRev = '" & docs(docIndex).getDocReview() & "'," & _
"docDate = '" & docs(docIndex).getDocDate() & "'" & _
" WHERE (" & _
"docNo = '" & docs(docIndex).getDocNo() & "');"
Else
'docNo does not exist - insert
strSQL = "INSERT INTO tbl_docs (docNo, docReviewStatus, docRev, docDate) " & _
"SELECT '" & docs(docIndex).getDocNo() & "'" & _
"," & docs(docIndex).getDocStatus() & _
",'" & docs(docIndex).getDocReview() & "'" & _
",'" & docs(docIndex).getDocDate() & "'" & _
";"
End If
DoCmd.SetWarnings False
DoCmd.RunSQL strSQL
DoCmd.SetWarnings True
MsgBox strSQL
Next
updateDocuments = docIndex
End Function
However, when the function is called (with tbl_docs empty), it only inserts one record and the SQL string thereafter becomes the update statement.
Is there a common issue when DCount() is used in a loop? Does anyone have any experience with this logical error?
Your check has a slight but important error:
exists = DCount("docNo", "tbl_docs", "docNo = '" & docs(docIndex).getDocNo() & "'" > 0)
should be
exists = DCount("docNo", "tbl_docs", "docNo = '" & docs(docIndex).getDocNo() & "'") > 0
or if exists isn't bool, but simply the count, then
exists = DCount("docNo", "tbl_docs", "docNo = '" & docs(docIndex).getDocNo() & "'")
You can simplify and speed up this a bit using DAO, where you can do the search and update/edit in one go:
Public Function updateDocuments(docs() As C_Document) As Long
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim docIndex As Long
Dim strSQL As String
strSQL = "Select * From tbl_docs"
Set db = Application.CurrentDb
Set rs = db.OpenRecordset(strSQL)
'Loop through all imported documents
For docIndex = LBound(docs) To UBound(docs)
rs.FindFirst "docNo = '" & docs(docIndex).getDocNo() & "'"
If rs.NoMatch Then
'docNo does not exist - insert
rs.AddNew
rs!docNo.Value = docs(docIndex).getDocNo()
Else
'docNo entry already exists - update
rs.Edit
End If
rs!docReviewStatus.Value = docs(docIndex).getDocStatus()
rs!docRev.Value = docs(docIndex).getDocReview()
rs!docDate = docs(docIndex).getDocDate()
rs.Update
Next
rs.Close
updateDocuments = docIndex
End Function
I am trying to import data from Excel into Access. Both 2010. Everything worked perfectly until I came across a cell that contained [text 'A' text]. Access completely stops the Sub at this point. When I manually change the Excel cell to [text A text] or the '' to ``, everything works perfectly again. But having to manually changing the source Excel defeats the purpose.
How do I import an Excel sheet when one or more cells contain [ 'A' ]?
Thank you in advance for any help.
'This checks if file exsist, imports file, then imports any sequential files.
Option Explicit
Public Sub ImportXL2(bolJustExcelFile As Boolean, Optional bolRefresh As Boolean)
Dim rstXL As DAO.Recordset
Dim x As Integer, y As Long
Dim strPath1 As String, strPath2 As String
Dim strPN As String, strDescription As String, strPrime As String
Dim intOHB As Integer, sngCost As Single, intMin As Integer, intMax As Integer
Dim strCode As Integer, strNumber As String, strDate As String, strQty As Integer, strRepairable As String, strEntity As String
DoCmd.SetWarnings False
DoCmd.RunSQL "DELETE FROM ExcelFile"
If bolJustExcelFile = False Then
DoCmd.RunSQL "DELETE FROM ExcelFileCombined"
End If
For x = 1 To 10
DoCmd.RunSQL "DELETE FROM ExcelFiletemp"
strPath1 = Environ("userprofile") & "\Desktop\Folder\ExcelFile.xlsx"
strPath2 = Environ("userprofile") & "\Desktop\Folder\ExcelFile" & x & ".xlsx"
If x = 1 Then
If FileExists(strPath1) = -1 Then
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12, "ExcelFiletemp", strPath1, False, "A:L"
Else
If bolRefresh = True Then
MsgBox "ExcelFile File Not Found", , "Missing ExcelFile File"
End If
Exit For
End If
Else
If FileExists(strPath2) = -1 And bolJustExcelFile = False Then
DoCmd.TransferSpreadsheet acImport, acSpreadsheetTypeExcel12, "ExcelFiletemp", strPath2, False, "A:L"
Else
GoTo SkipXL
End If
End If
Set rstXL = CurrentDb.OpenRecordset("SELECT * FROM ExcelFiletemp", dbOpenSnapshot)
rstXL.MoveLast
rstXL.MoveFirst
For y = 1 To 4
rstXL.MoveNext
Next y
strEntity = Right(rstXL![F1], 6)
For y = 1 To 4
rstXL.MoveNext
Next y
On Error GoTo ErrHandler
For y = 1 To rstXL.RecordCount - 8
strPN = rstXL![F1]
strDescription = rstXL![F2]
strPrime = rstXL![F3]
intOHB = rstXL![F4]
sngCost = rstXL![F5]
intMin = rstXL![F6]
intMax = rstXL![F7]
strCode = rstXL![F8]
strRepairable = rstXL![F12]
If x = 1 Then
DoCmd.RunSQL "INSERT INTO ExcelFile (PN, Description, Prime, OHB, Cost, Min, Max, Code, Repairable, Entity) VALUES ('" & strPN & "','" & strDescription & "','" & strPrime & "'," & intOHB & "," & sngCost & "," & intMin & "," & intMax & "," & strCode & ",'" & strRepairable & "','" & strEntity & "');"
End If
If bolJustExcelFile = False Then
DoCmd.RunSQL "INSERT INTO ExcelFileCombined (PN, Description, Prime, OHB, Cost, Min, Max, Code, Repairable, Entity) VALUES ('" & strPN & "','" & strDescription & "','" & strPrime & "'," & intOHB & "," & sngCost & "," & intMin & "," & intMax & "," & strCode & ",'" & strRepairable & "','" & strEntity & "');"
End If
rstXL.MoveNext
Next y
rstXL.Close
SkipXL:
Next x
Set rstXL = Nothing
DoCmd.SetWarnings True
ErrHandler:
If Err.Number = 94 Then 'Invalid use of Null
rstXL.MoveNext
End If
End Sub
You can escape single quotes by doubling them up.
Function EscQ(text As String)
EscQ = Replace(text, "'", "''")
End Function
Usage:
DoCmd.RunSQL "INSERT INTO ExcelFileCombined (PN, Description, Prime, OHB, Cost, Min, Max, Code, Repairable, Entity) VALUES ('" & EscQ(strPN) & "','" & EscQ(strDescription) & "','" & EscQ(strPrime) & "'," & intOHB & "," & sngCost & "," & intMin & "," & intMax & "," & strCode & ",'" & EscQ(strRepairable) & "','" & EscQ(strEntity) & "');"
I think using recordset to add new record will somehow make you worry free about SQL Syntax getting wrong because of special characters e.g. single or double quotes. You can try add a function:
Function insrt_item(rstXL as DAO.Recordset, tbl_dest as String) ' set tbl_dest to ExcelFile or ExcelFileCombined since they are same fields anyway
With currentdb.OpenRecordSet(tbl_dest)
.AddNew
!PN = rstXL!F1
!Description = rstXL!F2
'.. add more fields here
.Update
.Close
End With
End Function
Please help below code is not generating the mail and hangs access application:
Where is issue as when I dont do dQuery Processing Email Generates properly but dont include subform records aswell.
Without Subform Details Mail is something like this Email Generated with Proper variables present on MainForm
Private Sub InformCustomer_Click()
On Error GoTo Err_InformCustomer_Click
Dim CustName As String ' Customer Name
Dim varTo As Variant '-- Address for SendObject
Dim stText As String '-- E-mail text
Dim DelDate As Variant '-- Rec date for e-mail text
Dim stSubject As String '-- Subject line of e-mail
Dim stOrderID As String '-- The Order ID from form
Dim strSQL As String '-- Create SQL update statement
Dim errLoop As Error
Dim dQuery As String
Dim MyDb As DAO.Database
Dim rs As DAO.Recordset
stOrderID = Me![OdrID]
strSQL = "SELECT BrandName, ModelName, Status " _
& " FROM OrderProdDetails " _
& " WHERE (OrdID)=" & stOrderID & ";"
Set MyDb = CurrentDb
Set rs = CurrentDb.OpenRecordset(strSQL, dbOpenDynaset)
While Not rs.EOF
dQuery = dQuery & rs![BrandName].Value & vbTab & rs![ModelName].Value & rs![Status].Value & vbCrLf
Wend
Set rs = Nothing
CustName = Me![CustName]
varTo = Me![CustEmail]
stSubject = ":: Update - Oder Status ::"
stOrderID = Me![OdrID]
DelDate = Me![OdrDeliveryDate]
stText = "Dear" & CustName & Chr$(13) & _
"You have been assigned a new ticket." & Chr$(13) & Chr$(13) & _
"Order Number: " & stOrderID & Chr$(13) & _
_
"Please refer to your order status " & Chr$(13) & _
"Exp Delevery Date: " & DelDate & Chr$(13) & Chr$(13) & _
dQuery & Chr$(13) & _
"This is an automated message. Please do not respond to this e-mail."
'Write the e-mail content for sending to assignee
DoCmd.SendObject , , acFormatTXT, varTo, , , stSubject, stText, True
MsgBox "Done"
Exit Sub
Err_InformCustomer_Click:
MsgBox Err.Description
End Sub
You have created an endless loop.
While Not rs.EOF
dQuery = dQuery & rs![BrandName].Value & vbTab & rs![ModelName].Value & rs![Status].Value & vbCrLf
' This is missing -->
rs.MoveNext
Wend
I need your help. I woulod like to change one char by another but in all database and i have several table and fields. So i'm building a function in VB but that change nothing and i have no error. I think that my condition is false but i don't see how to correct it :/
Public Sub updateField()
Dim db As DAO.Database, td As DAO.TableDef, field As DAO.field
Dim rs As DAO.Recordset, sSQL As String, sData As String
Set db = CurrentDb
Change = "\"""
replaced = """"
'each table in db
For Each tbd In db.TableDefs
'each field in table
For Each fld In tbd.Fields
'check if String Data have my character
If InStr(1, fld.Name, Change) Then
sSQL = "UPDATE " & tbd.Name & " SET " & fld.Name & " = replace([" & fld.Name & "], " & Change & ", " & replaced & ")"
db.Execute sSQL
End If
Next
Next
End Sub
EDIT :
I finally find what's wrong. if some people are interested :
Set db = CurrentDb
Change = "\"""
replaced = """"
'each table in db
For Each tbd In db.TableDefs
'each field in table
For Each fld In tbd.Fields
If Left(tbd.Name, 4) <> "MSys" And Left(tbd.Name, 4) <> "~TMP" Then
If fld.Type = dbText Or fld.Type = dbMemo Then
sSQL = "UPDATE " & tbd.Name & " SET " & fld.Name & " = replace([" & fld.Name & "],'" & Chr(92) + Chr(34) & "','" & Chr(34) & "')"
db.Execute sSQL
'Debug.Print (sSQL)
End If
End If
Next
Next
Thx for your help guys ;)
If it should help there my solution :
Public Sub updateField()
Dim db As DAO.Database, td As DAO.TableDef, field As DAO.field
Dim rs As DAO.Recordset, sSQL As String, sData As String, change As String, replace As String
change = "\'"
replace = "'"
' simple quote = 39
' doulbe quote = 34
' antislash = 92
' retour chariot = 13
' n = 110
' r = 114
Set db = CurrentDb
'each table in db
For Each tbd In db.TableDefs
'each field in table
For Each fld In tbd.Fields
If Left(tbd.Name, 4) <> "MSys" And Left(tbd.Name, 4) <> "~TMP" Then
If fld.Type = dbText Or fld.Type = dbMemo Then
' \r\n
'sSQL = "UPDATE " & tbd.Name & " SET [" & fld.Name & "] = replace([" & fld.Name & "],'\r\n','" & Chr(13) & Chr(10) & "');"
' \"
'sSQL = "UPDATE " & tbd.Name & " SET [" & fld.Name & "] = replace([" & fld.Name & "],'" & Chr(92) + Chr(34) & "','" & Chr(34) & "');"
'db.Execute sSQL
sSQL = "UPDATE " & tbd.Name & " SET [" & fld.Name & "] = replace([" & fld.Name & "],'\''','''');"
db.Execute sSQL
'Debug.Print (sSQL)
End If
End If
Next
Next
End Sub
That's works for me ;)
There's a csv file like so, I can read it easily enough with the code below. But as you can see there are multiple name1, group1, status1, name2, group2, etc columns in the csv. Each user will have a different number of columns. I was wondering if there is a way to use wild cards where I'm calling objRecordset.Fields.Item("Group1") something like ("Group%") or if I can auto increment the number until no records are found
UserName,Domain,Site,MCO,Name1,Group1,Status1,Name2,Group2,Status2,Name3,Group3,Status3
Paolina,AA,Athens,Greece,Adobe Acrobat Pro,ACROBAT009,Live,,,,,,
George,AA,Athens,Greece,SpotFire 2.20,SPOTFIRE220,Live,,,,,,
option explicit
Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adCmdText = &H0001
Dim strPathtoTextFile, objConnection, objRecordSet, objNetwork
Dim wshshell, Username
Set objConnection = CreateObject("ADODB.Connection")
Set objRecordSet = CreateObject("ADODB.Recordset")
Set objNetwork = CreateObject("WScript.Network")
userName = objNetwork.UserName
strPathtoTextFile = "C:\Hunter\vbs\" 'must have a trailing \
objConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & strPathtoTextFile & ";" & _
"Extended Properties=""text;HDR=YES;FMT=Delimited"""
objRecordset.Open "SELECT * FROM Users.txt where [user name] like '" & UserName & "'", _
objConnection, adOpenStatic, adLockOptimistic, adCmdText
Do Until objRecordset.EOF
Wscript.Echo "Name: " & objRecordset.Fields.Item("User Name")
Wscript.Echo "Group: " & objRecordset.Fields.Item("Group1")
Wscript.echo "Status:" & objRecordset.Fields.Item("Status1")
objRecordSet.MoveNext
Loop
Your example suggests that the maximum group number is the last field, so perhaps:
objRecordset.Open "SELECT * FROM Users.txt where [user name] like '" _
& UserName & "'", _
objConnection, adOpenStatic, adLockOptimistic, adCmdText
MaxNum = _
Replace(objRecordset.Fields(objRecordset.Fields.Count-1).Name,"Status","")
Do Until objRecordset.EOF
Wscript.Echo "Name: " & objRecordset.Fields.Item("User Name")
For i=1 to MaxNum
Wscript.Echo "Group: " & objRecordset.Fields.Item("Group" & i)
Wscript.echo "Status:" & objRecordset.Fields.Item("Status" & i)
Next
objRecordSet.MoveNext
Loop
I have not tested, but the general idea should hold.