I have to document an MS Access database with many many macros queries, etc. I wish to use code to extract each SQL query to a file which is named the same as the query, eg if a query is named q_warehouse_issues then i wish to extract the SQL to a file named q_warehouse_issues.sql
I DO NOT WISH TO EXPORT THE QUERY RESULT SET, JUST THE SQL!
I know I can do this manually in Access, but i am tired of all the clicking, doing saveas etc.
This should get you started:
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Set db = CurrentDB()
For Each qdf In db.QueryDefs
Debug.Print qdf.SQL
Next qdf
Set qdf = Nothing
Set db = Nothing
You can use the File System Object or the built-in VBA File I/O features to write the SQL out to a file. I assume you were asking more about how to get the SQL than you were about how to write out the file, but if you need that, say so in a comment and I'll edit the post (or someone will post their own answer with instructions for that).
Hope this helps.
Public Function query_print()
Dim db As Database
Dim qr As QueryDef
Set db = CurrentDb
For Each qr In db.QueryDefs
TextOut (qr.Name)
TextOut (qr.SQL)
TextOut (String(100, "-"))
Next
End Function
Public Sub TextOut(OutputString As String)
Dim fh As Long
fh = FreeFile
Open "c:\File.txt" For Append As fh
Print #fh, OutputString
Close fh
End Sub
This solution include fields in query
Public Sub ListQueries()
' Author: Date: Contact:
' André Bernardes 09/09/2010 08:45 bernardess#gmail.com http://al-bernardes.sites.uol.com.br/
' Lista todas as queries da aplicação.
' Listening:
Dim i As Integer
Dim j As Integer
Dim k As Integer
Dim l As Integer
On Error Resume Next
For i = 0 To CurrentDb.QueryDefs.Count - 1
Debug.Print "Query: " & CurrentDb.QueryDefs(i).Name
For j = 0 To CurrentDb.QueryDefs(i).Fields.Count - 1
Debug.Print "Field " & CurrentDb.QueryDefs(i).Fields(j).Name
Next
Debug.Print " SQL: " & CurrentDb.QueryDefs(i).SQL
Next
End Sub
In the VB Window, click Tools->References....
In the References window add the dependency Microsoft Scripting Runtime by checking it off.
Then this code will export the queries to a file suitable for using grep on:
Sub ExportQueries()
Dim fso As New FileSystemObject
Dim stream As TextStream
Set stream = fso.CreateTextFile("e:\temp\queries.txt")
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Set db = CurrentDb()
For Each qdf In db.QueryDefs
stream.writeline "Name: " & qdf.Name
stream.writeline qdf.SQL
stream.writeline "--------------------------"
Next qdf
Set qdf = Nothing
Set db = Nothing
End Sub
I modified #andre-bernardes's code to use
"|" separators before the query names
and ":" separators before the SQL statements.
The different separators make it easier to parse the Queries.txt file with python and create a dictionnary of queries and SQL statements.
You can then use this dictionary to create views in an SQLite table for example.
VBA code to extract the SQL queries
Public Sub ListQueries()
' Modified from André Bernardes
Dim i As Integer
Dim ff As Long
ff = FreeFile()
Open "C:\Dev\Queries.txt" For Output As #ff
On Error Resume Next
For i = 0 To CurrentDb.QueryDefs.Count - 1
Debug.Print "|" & CurrentDb.QueryDefs(i).Name & ":"
Print #ff, "|" & CurrentDb.QueryDefs(i).Name & ":"
Debug.Print CurrentDb.QueryDefs(i).SQL
Print #ff, CurrentDb.QueryDefs(i).SQL
Next
End Sub
Python code to parse Queries.txt into a dictionary
queries_file = open(data_path + '/Queries.txt')
queries = queries_file.read().split('|')
l = [x.split(':') for x in queries]
l.pop(0)
table_name_to_query = {name: query for name, query in l}
Create SQLite views from the Access queries
import sqlite3
conn = sqlite3.connect('example.db')
c = conn.cursor()
for table, query in table_name_to_query.items():
try:
c.execute("CREATE VIEW `%s` AS %s" % (table,query))
print("\n\n"+ table + " passed")
print(query)
except Exception as e:
print("\n\n"+ table + " error")
print(e)
print(query)
Related
I have a form that has a multi-selection listbox based on a query of items that have a specific field that is blank (UserID). I would like to select a UserID from a combobox and click a button to have all selected records modified to have that UserID. (I would also like to update the DateAssigned field to whatever the current date is). CaseID is the unique value in the table.
Sample Form Picture
(The combo box has two columns, the second one has the actual ID I'd want to use).
I've looked at multiple different posts on here like this but I haven't been able to get it to work. Here's an example of a code I found and tried, altered slightly.
Private Sub AssignButton_Click()
Dim lCnt As Long
Dim lID As Long
Dim sSQL_Update As String
Dim sText_1 As String
Dim bSuccess As Boolean
sText_1 = Me.ComboBox
With Me.ToAssignList
For lCnt = 1 To .ListCount
If .Selected(lCnt) Then
lID = .Column(4, lCnt - 1)
'Example update for 1 column
sSQL_Update = "UPDATE MainData SET UserID = '" & sText_1 & "' WHERE CaseID = " & lID & ";"
bSuccess = Update_Statement(sSQL_Update)
End If
Next
End With
End Sub
Public Function Update_Statement(sUpdate_Stmt) As Boolean
Dim db As Database
Set db = CurrentDb
db.Execute (sUpdate_Stmt)
End Function
When I try running this nothing happens.
Thank you!
Hy, Some remarks and tweaks to your code :
First enable the direct screen :
This will enable you to use the debug function.
Is the field : UserID in the table Maindata a text field ? If so, fine, otherwise you should alter the string to :
"UPDATE MainData SET UserID = " & Cint(sText_1) & " WHERE CaseID = " & lID & ";"
Then it would be better to create different functions in a module for what you are trying to do. But ok, this is not your main concern right now...
Try :
Private Sub AssignButton_Click()
Dim lCnt As Long
Dim lID As Long
Dim sSQL_Update As String
Dim sText_1 As String
Dim bSuccess As Boolean
sText_1 = Me.ComboBox
With Me.ToAssignList
For lCnt = 1 To .ListCount
If .Selected(lCnt) Then
lID = .Column(4, lCnt - 1)
'Example update for 1 column
sSQL_Update = "UPDATE MainData SET UserID = '" & sText_1 & "' WHERE CaseID = " & lID & ";"
'
'Check your sql statement and add it to stack overflow if it still is not working
'
Debug.Print sSQL_Update
'
bSuccess = Update_Statement(sSQL_Update)
End If
Next
End With
End Sub
There is should be a logical check in the code bellow to see if the update is done, anyhow, the code bellow should work and return a true value if the update doesn't produce an error... it's not good code but ok.
Public Function Update_Statement(sUpdate_Stmt) As Boolean
Dim Currentdb As Database
Set Currentdb = Currentdb
Call Currentdb.Execute(sUpdate_Stmt, dbSeeChanges)
Update_Statement = True
End Function
Good luck !
I have a long text field (called "reporttext") that someone is importing a bunch of text that needs to be separated and appended into another table. For each case, there's a "[]" character that is supposed to separate each case. I want my code to look for the first [] and second [], append the text to another table and then loop. So the next case would be the text between the second [] and third [].
Here's my string
Reporttext: [] ksfjjls [] 42244 [] ####
I would want this to append to a new table called "notes" where it would be like this:
Reporttext
ksfjjls
42244
####
I used a macro to count the number of [] in the text file to know how many times to run the loop, but this, along with the rest of my code just isn't happening. I know my code is wrong, but I know with a few tweaks it'll get there. Any help is appreciated.
lengthofnote = Len([reporttext])
start = InStr([reporttext], "[]")
startplus3 = [start] + 3
'find number of cases
firstcase = 1
numcases = StringCountOccurrences([reporttext], "[]")
Dim LCounter As Integer
For LCounter = [firstcase] To [numcases]
revisedreporttext = Mid([reporttext], [startplus3], [lengthofnote])
secondposition = InStr([revisedreporttext], "[]")
nextreporttext = Mid([reporttext], [startplus3], [secondposition])
Add_reporttext = "INSERT INTO notes(reporttext) values ('" & nextreporttext & "');"
DoCmd.RunSQL Add_reporttext
firstcase = firstcase + 1
startplus3 = secondposition
secondposition = secondposition + 4
Next LCounter
#Zev Spitz is correct in that you could use Split() to accomplish this. You could use something like this
Option Compare Database
Option Explicit
Sub SplitLongTextField()
Dim rs As Recordset
Dim reportTextArr
Dim qString As String
Dim i As Long
qString = "SELECT [reporttext] FROM [Table1]" '<- replace [Table1] with the name of your table with the Long Text field
Set rs = CurrentDb.OpenRecordset(qString)
If Not rs.EOF Then
reportTextArr = Split(rs.Fields("reporttext"), "[]")
End If
For i = LBound(reportTextArr) To UBound(reportTextArr)
If Not reportTextArr(i) = "" Then
DoCmd.RunSQL "INSERT INTO notes(reporttext) VALUES('" & reportTextArr(i) & "');"
End If
Next i
rs.Close
End Sub
If you needed to do this for multiple records from your initial table then you could loop through the entire table and loop the operation like
Option Compare Database
Option Explicit
Sub SplitLongTextField()
Dim rs As Recordset
Dim reportTextArr
Dim qString As String
Dim i As Long
qString = "SELECT [reporttext] FROM [Table1]" '<- replace [Table1] with the name of your table with the Long Text field
Set rs = CurrentDb.OpenRecordset(qString)
Do Until rs.EOF
reportTextArr = Split(rs.Fields("reporttext"), "[]")
For i = LBound(reportTextArr) To UBound(reportTextArr)
If Not reportTextArr(i) = "" Then
DoCmd.RunSQL "INSERT INTO notes(reporttext) VALUES('" & reportTextArr(i) & "');"
End If
Next i
rs.MoveNext
Loop
rs.Close
End Sub
Assuming the string always starts with [] and preference is to return a single string, consider:
Replace(Mid(reporttext, 4), "[] ", vbCrLf)
I'm trying to import an SQL file into excel via VBA in order to return the SQL code as one string, however I'm getting tiny squares (carriage returns?) between each character when I import the SQL as a string - not a clue why! It's worked before in other files, with different SQL, so I'm not sure what I've done wrong.
Function ImportSQLText(FileExt, FileSQLName)
'//Needs Microsoft Scripting Runtime Ref
'//and microsoft active x data objects 2.8
Dim ReadText As String, newLine As String
Dim fso As FileSystemObject: Set fso = New FileSystemObject
Set txtStream = fso.OpenTextFile(FileExt & fileName, ForReading, False)
ReadText = " "
Do While Not txtStream.AtEndOfStream
newLine = txtStream.ReadLine
If InStr(newLine, "[input-sDte]") > 0 Then
ReadText = ReadText & Replace(newLine, "[input-sDte]", sDte) & vbCrLf
ElseIf InStr(newLine, "[input-eDte]") > 0 Then
ReadText = ReadText & Replace(newLine, "[input-eDte]", eDte) & vbCrLf
Else
ReadText = ReadText & newLine & vbCrLf
End If
Loop
txtStream.Close
ImportSQLText = ReadText
End Function
The SQL code looks like:
;if object_id('tempdb.#usr_fld') is not null
drop table #usr_fld
-- Creating Temp Table
CREATE TABLE #usr_fld([PLACE-REF] NVARCHAR(50)
,[PROJCODE] nvarchar(100)
,[CUORACLE] nvarchar(100));
Any input would be greatly appreciated - googling it is not helping me this time.
You almost definitely have a unicode file. There is an optional fourth parameter on the OpenTextfile method of FSO:
Const TriStateTrue = -1
Set txtStream = fso.OpenTextFile(FileExt & fileName, ForReading, False, TriStateTrue)
Just swap out your line for these two and it might fix the issue.
I'm New to this forum so please be patient with me, thanks. I am not an expert in VBA. I am from Norway so my english is not the best.
I need to create a text-file generator. The text-files are beeing used as inspection reports in a pipe inspection program.
The text-file must look like this.
[Inspection1]
PipeID=112
FromPointNo=8696
ToPointNo=8292
Street=Trykkeriveien
Date=30.07.2009
Signature=Tho
Weather=B
PreWashed=N
ArchiveRef=
PipeFeature=AF
Material=Bet
Dimension=400
PipeForm=S
VerticalDim=
PipeLength=94,24
Comment= SM=9,6
SD=0
Obs=Distance;Observation;Type;ClockPos;Rank;Photo;VideoPos;Comment
Obs1=0,00;SI;;;0;No;;Start inspection
Obs2=4,38;PC;;0;1;No;;Pipe connection, from 01-12
Obs3=11,55;PC;;2;2;No;;Pipe connection, from 00-11
Obs4=21,21;PC;;1;1;No;;Pipe connection, from 02-12
Obs5=22,56;FI;;;0;No;;Inspection finished
For solving this i have created two tables, one for the inspection and the other for the inspection details.
The difficult part is how to deal with the header (the upper part of the text-file) and the details below.
I have a built up a string that contains the header and it looks exactely like it should. BUT!!! The lower part (the part containing the oberservation details)
I have not solved. I have tried several approaches, but have not suceeded - YET.
Any suggestion on how to proceed?
Best Regards from Anders
This sounds like a job for ADODB.Recordset.GetString!!! This method will wrap field and record values using ColumnDelimiter and RowDelimiter respectively. It allows for fast creation of csv file and even HTML tables.
MSDN - GetString Method (ADO)
Variant = recordset.GetString(StringFormat, NumRows, ColumnDelimiter, RowDelimiter, NullExpr)
test.txt
test.html
Sub TestFile()
Const FILEPATH = "C:\Users\Owner\Documents\stack-overflow\Inspection Reports\test.txt"
Dim OutputString As String
OutputString = getInspectionDetails & vbCrLf & vbCrLf & vbCrLf & getInspection
Open FILEPATH For Output As #1
Print #1, OutputString
Close #1
End Sub
Function getInspection(Optional ColumnDelimeter = ";", Optional RowDelimeter = vbCrLf) As String
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
rs.Open "[Inspection]", CurrentProject.Connection
'RowDelimeter
getInspection = rs.GetString(ColumnDelimeter:=ColumnDelimeter, RowDelimeter:=RowDelimeter, NullExpr:=" ")
rs.Close
Set rs = Nothing
End Function
Function getInspectionDetails(Optional ColumnDelimeter = ";", Optional RowDelimeter = vbCrLf) As String
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
rs.Open "[Inspection Details]", CurrentProject.Connection
getInspectionDetails = rs.GetString(ColumnDelimeter:=ColumnDelimeter, RowDelimeter:=RowDelimeter, NullExpr:=" ")
rs.Close
Set rs = Nothing
End Function
Sub TestHTML()
Const FILEPATH = "C:\Users\Owner\Documents\stack-overflow\Inspection Reports\test.html"
Dim OutputString As String, tBody As String
OutputString = "<!DOCTYPE html><body><table>#tablebody</table></body></html>"
tBody = getInspection(getInspection("</td><td>", "</td></tr>" & vbCrLf & "<tr><td>"))
tBody = "<tr>" & Left(tBody, Len(tBody) - 4)
Open FILEPATH For Output As #1
Print #1, Replace(OutputString, "#tablebody", tBody)
Close #1
End Sub
All,
I'm trying to save a record for 1 record to a drive. I've spent about a day searching for a solution so this is a last ditch effort for some help. I am not a developer by any stretch of the imagination so please, go easy.
Code is below.
Table where record is located: tracker.
Field I am searching based on: ReqID - where ReqID = the record I am entering, find the attachment and move it to a location.
Dim db As DAO.Database
Dim rsChild As DAO.Recordset2
Dim ReqID As String
ReqID = Me.Form![Text145]
Debug.Print ReqID
Set db = CurrentDb
Set rsChild = db.OpenRecordset("Select * from tracker Where " & ReqID & " = [tracker].[ID]", dbOpenDynaset)
Debug.Print rsChild.RecordCount
If (rsChild.EOF = False) Or (rsChild.BOF = False) Then
While Not rsChild.EOF
rsChild("FileData").SaveToFile "C:\Users\<folder>\"
rsChild.Delete
Wend
End If
You actually need to use two Recordset objects: one for the main record and another for the attachment(s) associated with that record. This is the sample code that works for me, where [tblTest] is the name of the table and [Attachments] is the name of the Attachment field:
Option Compare Database
Option Explicit
Sub SaveAllAttachments()
Dim cdb As DAO.Database
Set cdb = CurrentDb
Dim rstMain As DAO.Recordset
Set rstMain = cdb.OpenRecordset("SELECT Attachments FROM tblTest WHERE ID=1", dbOpenDynaset)
rstMain.Edit
Dim rstChild As DAO.Recordset2
Set rstChild = rstMain.Fields("Attachments").Value
Do Until rstChild.EOF
Dim fileName As String
fileName = rstChild.Fields("FileName").Value
Debug.Print fileName
Dim fld As DAO.Field2
Set fld = rstChild.Fields("FileData")
fld.SaveToFile "C:\Users\Gord\Desktop\" & fileName
rstChild.Delete ' remove the attachment
rstChild.MoveNext
Loop
rstChild.Close
rstMain.Update
rstMain.Close
End Sub