I have a macro that I'm trying to build in Access which will change the source table on a set of queries. Here is what I've built (based off already written code that I found on a forum):
Function ReplaceSources()
Call SourceQueries
End Function
Sub SourceQueries()
Call UpdateSource("YYYY_Count_of_items_by_floor", Building_Audit_2021, Building_Audit_YYYY)
End Sub
Sub UpdateSource(QueryName, CurrentSourceTable, NewSourceTable)
Dim strQryName, strCTbl, strNTbl, strCsql, strNsql As String
Dim defqry As DAO.QueryDef
strQryName = QueryName
strCTbl = CurrentSourceTable
strNTbl = NewSourceTable
Set defqry = CurrentDb.QueryDefs(strQryName)
strCsql = defqry.SQL
strNsql = Replace(strCsql, strCTbl, strNTbl)
defqry.SQL = strNsql
defqry.Close
End Sub
When I use the RunCode option in the macro builder using function name ReplaceSources(), nothing happens. I get no errors, I can step through the code with no issues, and adding Debug.Print lines throughout the function and subs does nothing. What is preventing this function from doing anything?
ETA:
Maybe it will help if I add the other two parts of code that I'm piecing together with this one. Before the above code, I run:
Function Copy_audit_table()
On Error GoTo Copy_audit_table_Err
Dim strPath As String
strPath = CurrentProject.FullName
DoCmd.TransferDatabase acImport, "Microsoft Access", strPath, acTable, "Building_Audit_2021", "Building_Audit_YYYY", True
DoCmd.CopyObject "", "YYYY_Count_of_items_by_floor", acQuery, "2021_Count_of_items_by_floor"
Copy_audit_table_Exit:
Exit Function
Copy_audit_table_Err:
MsgBox Error$
Resume Copy_audit_table_Exit
End Function
Then after the code in question, I run:
Function Copy_audit_table_rename()
On Error GoTo Copy_audit_table_rename_Err
Dim AuditYear As Variant
AuditYear = InputBox("Enter audit year (YYYY)")
Dim strPath As String
strPath = CurrentProject.FullName
DoCmd.Rename "Building_Audit_" & AuditYear, acTable, "Building_Audit_YYYY"
DoCmd.Rename AuditYear & "_Count_of_items_by_floor", acQuery, "YYYY_Count_of_items_by_floor"
Copy_audit_table_rename_Exit:
Exit Function
Copy_audit_table_rename_Err:
MsgBox Error$
Resume Copy_audit_table_rename_Exit
End Function
I'm not too familiar with VBA, so most of this is code that I found elsewhere that I was able to piece together. I know that I can use the macro builder to run each Function, but I really don't know any other ways. If there are any recommended tutorials that will help me code what I want to do, I'd like to read them.
You must execute the query for something to happen.
And skip the macro and the function. All you need is to call:
Sub UpdateSource(QueryName As String, CurrentSourceTable As String, NewSourceTable As String)
Dim strCsql As String
Dim defqry As DAO.QueryDef
Set defqry = CurrentDb.QueryDefs(QueryName)
strCsql = defqry.SQL
strNsql = Replace(strCsql, CurrentSourceTable, NewSourceTable)
defqry.SQL = strNsql
defqry.Execute
defqry.SQL = strCsql
defqry.Close
End Sub
Related
I need to write code that goes to a specific path and imports data from it,
then goes to another path and do the same.
I need that if path num 1 does not exist, it will jump direct to path num 2.
I wrote a sub for each path. there is a way to do something like:
if error goto sub ___ ?
Thanks in advance
Not directly, but you can do something like
On Error Goto error_sub1
and at the bottom of your function, write
error_sub1:
'ToDo - put your calling code here.
Elsewhere in you function you can switch the error handler to a different label:
On Error Goto error_sub2
and so on.
Try this:
Sub testSO()
On Error GoTo err
I=5/0
Exit Sub
err:
<your sub procedure here>
End Sub
Remember to include Exit Sub or else it will still run even without error!
Would it not be better to avoid the error in the first place and check whether the file exists before attempting to open it?
Sub Test()
Dim sFile1 As String
Dim sFile2 As String
Dim wrkBk As Workbook
On Error GoTo Error_Handler
sFile1 = "C:\Users\Desktop\MyFile1.xls"
sFile2 = "C:\Users\Desktop\MyFile2.xls"
If FileExists(sFile1) Then
Set wrkBk = Workbooks.Open(sFile1)
ElseIf FileExists(sFile2) Then
Set wrkBk = Workbooks.Open(sFile2)
Else
Err.Raise 513, , "File Not Found."
End If
wrkBk.Worksheets(1).Range("A1") = "Opened this file."
On Error GoTo 0
Fast_Exit:
'Any tidying up that needs doing.
Exit Sub
Error_Handler:
MsgBox Err.Description, vbExclamation + vbOKCancel, _
"Error: " & CStr(Err.Number)
Err.Clear
Resume Fast_Exit
End Sub
Public Function FileExists(ByVal FileName As String) As Boolean
Dim oFSO As Object
Set oFSO = CreateObject("Scripting.FileSystemObject")
FileExists = oFSO.FileExists(FileName)
End Function
So, dumb question, but I can't figure it out. I have the following code that searches for a file path name and I believe adds the record to a table (untested). But, the problem is I am unable to Call this subroutine. I'd like to be able to click a button on a form and run. Does anyone know how I do this? thank you!
Public Function SelectFile() As String
Dim f As FileDialog
Set f = Application.FileDialog(msoFileDialogOpen)
With f
.AllowMultiSelect = False
.Title = "Please select file to attach"
If .Show = True Then
SelectFile = .SelectedItems(1)
Else
Exit Function
End If
End With
Set f = Nothing
End Function
Public Sub AddAttachment(ByRef rstCurrent As DAO.Recordset, ByVal strFieldName As String, ByVal strFilePath As String)
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
'Ask the user for the file
Dim filepath As String
filepath = SelectFile()
'Check that the user selected something
If Len(filepath) = 0 Then
Debug.Assert "No file selected!"
Exit Sub
End If
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset("Table1")
''''change this
'Add a new row and an attachment
rst.AddNew
AddAttachment rst, "Files", filepath
rst.Update
'Close the recordset
rst.Close
Set rst = Nothing
Set dbs = Nothing
End Sub
You would add an event procedure to the button in question:
In Form Design mode, click on the button
In the Properties Sheet, select the builder [...] button of the On Click event
You will go to the VBA editor. Enter code like:
Private Sub cmdAddAttachment_Click()
AddAttachment Nothing, "", ""
End Sub
That said, your AddAttachment routine has an apparent infinite loop. The line:
AddAttachment rst, "Files", filepath
Doesn't seem to actually fill any field values. In fact, variables rstCurrent, strFieldName and strFilePath are not used in the code. You probably will need to debug this routine before it will work.
I'm writing an automation script that will collect data from 4 emails that arrive during a day and sending a report email at the end of the day, I already figured out how to append text file that will be sent and how to search email for specific string that tell me if everything's alright.
But I have an issue. I put some code into Subs and Functions and it stopped work. itm.Body is not visible in Function CheckSafeSet, and what strange Else don't run if IF isn't ture.
Please help. If you have any suggestions to do it differently, smarter better simpler please tell me
Thanks Michal
Public Sub AppendTextFiles(safeset As String)
Open "C:\AppSupport\testfilew.txt" For Append As #1
Print #1, safeset
Close #1
End Sub
Function CheckSafeSet(safeset As String)
MsgBox ("1")
MsgBox (itm.Body)
If itm.Body Like safeset Then
MsgBox ("2")
Call AppendTextFiles("adfsdfasdfsergedgrrt")
Else:
MsgBox ("FAIL")
End If
End Function
Public Sub process_email(itm As Outlook.MailItem)
'Strings - Savegroups
Dim d1000i As String
Dim d1200i As String
Dim l0001i As String
l0001i = "*Savegroup: VNX_UK_NDMP_00:01*"
Dim l2000i As String
Dim lonparch01 As String
'lonparch01 = "*pnwifsvbbup03.r3-core.r3.aig.net:/root_vdm_1/vol_lonparch01_snap 42927:nsrndmp_save: Successfully done*"
lonparch01 = "*NDMP*"
Dim new_msg As MailItem
If itm.Body Like l0001i Then
MsgBox (itm.Body)
Call CheckSafeSet(lonparch01)
Else:
End If
End Sub
The issue is that you have not passed the itm object to the CheckSafeSet Function. YOu need to add itm As Outlook.MailItem to the signature of the CheckSafeSet Function and then pass the itm object
Public Sub AppendTextFiles(safeset As String)
Open "C:\AppSupport\testfilew.txt" For Append As #1
Print #1, safeset
Close #1
End Sub
Function CheckSafeSet(safeset As String, itm As Outlook.MailItem)
MsgBox ("1")
MsgBox (itm.Body)
If itm.Body Like safeset Then
MsgBox ("2")
Call AppendTextFiles("adfsdfasdfsergedgrrt")
Else
MsgBox ("FAIL")
End If
End Function
Public Sub process_email(itm As Outlook.MailItem)
'Strings - Savegroups
Dim d1000i As String
Dim d1200i As String
Dim l0001i As String
l0001i = "*Savegroup: VNX_UK_NDMP_00:01*"
Dim l2000i As String
Dim lonparch01 As String
'lonparch01 = "*pnwifsvbbup03.r3-core.r3.aig.net:/root_vdm_1/vol_lonparch01_snap 42927:nsrndmp_save: Successfully done*"
lonparch01 = "*NDMP*"
Dim new_msg As MailItem
If itm.Body Like l0001i Then
MsgBox (itm.Body)
Call CheckSafeSet(lonparch01, itm)
Else
End If
End Sub
I'm trying to call a function from a 3rd party Excel-add in a VBA-sub. The function loads data from a database into specified cells in the Excel workbook.The function I'm calling is huge and unfortunaly I can't post it in its entirety, but here are the first two lines:
Public Function loadFromDatabase(ByVal XLname As String, ByVal sMark As String)
Dim xlWB As Workbook
Then it declares a bunch of variables before running the following tests:
'
' Get the excel book and check if it is run in compatibility mode
'
Set xlWB = getXLBook(XLname)
If xlWB Is Nothing Then
loadFromDatabase = "Workbook '" + XLname + "' not found!"
Exit Function
End If
bExcel8Limits = True
If isExcel2007orLater Then
bExcel8Limits = bCheckCompMode(xlWB)
End If
Here I get this message: "Workbook " not found!" http://imgur.com/HQFAzoC .
The getXLBook function looks like this:
'
' Routine to get a specified Workbook
'
Function getXLBook(sName As String) As Workbook
Dim xlWB As Workbook
On Error Resume Next
Set xlWB = Nothing
Set xlWB = Application.Workbooks(sName)
On Error GoTo 0
Set getXLBook = xlWB
End Function
A hint here may be that I'm able to call the function from a Private Sub place in a worksheet like this...
Private Sub loadFromDB()
Dim res As Variant
res = Application.Run("loadFromDatabase", Me.Parent.Name, "")
If res <> "OK" Then
MsgBox res
End If
End Sub
...but not from a module in the same workbook like this
Sub loadFromDB_test()
Dim res As Variant
res = Application.Run("loadFromDatabase", XLname, sMark)
If res <> "OK" Then
MsgBox res
End If
End Sub
Any suggestions?
Edit: To clarify, it's when running loadFromDB_test the "Workbook not found" message pops up.
Edit 2: An obvious hotfix (that I didnt think of) is to just call the Private Sub in the worksheet from the Sub in the module.
Sub load_test_new()
Application.Run "Sheet1.loadFromDB"
End Sub
From a learning point of view this is clearly not a good solution as it is inefficient coding.
Based on the msgbox you display, you're passing an empty string to the function getXLBook. (within the scope of getXLBook this value is stored as sName, but the cause of the error is before you call this function).
So, somewhere in your code, before this:
Set xlWB = getXLBook(XLname)
You should have a line like this, where the right side of the statement assigns a string representing a full, valid filepath:
XLName = "C:\filename.xlsx"
I suspect that your code does not contain this assignment statement, so that should explain the error.
Using the FileSystemObject in VB/VBA (or native VBA calls, I guess) how can I:
Copy folder
Rename folder
So, something like:
mFSO.CopyAndRename(targetFolder, copyDirectory, copyFolderName)
I have basically done this myself but I would much prefer a more clean method call such as the above (and the CopyFolder method). This seems like a lot of code and a lot of potential failure points...
'
''requires reference to Microsoft Scripting Runtime
Public Function CopyDirectory(ByVal p_copyDirectory As String, p_targetDirectory As String, Optional p_newName As String = "") As Boolean
CopyDirectory = False
Dim m_fso
Set m_fso = New FileSystemObject
Dim mFolder, mNewFolder
If Not Me.DoesPathExist(p_copyDirectory) Then
Exit Function
Else
On Error GoTo errHandler
Set mFolder = m_fso.GetFolder(p_copyDirectory)
mFolder.Copy p_targetDirectory, False
'rename if a "rename" arg is passed
If p_newName <> "" Then
If DoesPathExist(p_targetDirectory & mFolder.Name) Then
Set mNewFolder = m_fso.GetFolder(p_targetDirectory & mFolder.Name)
mNewFolder.Name = "test" & CStr(Rnd(9999))
Else
End If
End If
CopyDirectory = True
On Error GoTo 0
Exit Function
End If
errHandler:
Exit Function
End Function
There is actually a method on Scripting.FileSystemObject called CopyFolder. It can be used to do both the copy and rename in one step, as follows:
Dim objFSO As Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.copyFolder "C:\Path\to\source\folder", "C:\Path\to\destination\folder" true
I found the code here: http://vba-tutorial.com/copy-a-folder-and-all-of-its-contents/
Hope this answers your question.
My Fav: SHFileOperation API
This also gives you the visual presentation of Folders being moved.
Option Explicit
Private Declare Function SHFileOperation Lib "shell32.dll" _
Alias "SHFileOperationA" (lpFileOp As SHFILEOPSTRUCT) As Long
Const FO_COPY = &H2 '~~> Copy File/Folder
Const FOF_SILENT = &H4 '~~> Silent Copy
Private Type SHFILEOPSTRUCT
hwnd As Long
wFunc As Long
pFrom As String
pTo As String
fFlags As Integer
fAborted As Boolean
hNameMaps As Long
sProgress As String
End Type
Private Sub Sample()
Dim lresult As Long, lFlags As Long
Dim SHFileOp As SHFILEOPSTRUCT
With SHFileOp
'~~> For Copy
.wFunc = FO_COPY
.pFrom = "C:\Temp"
.pTo = "C:\Temp2\"
'~~> For Silent Copy
'.fFlags = FOF_SILENT
End With
lresult = SHFileOperation(SHFileOp)
'~~> SHFileOp.fAborted will be true if user presses cancel during operation
If lresult <> 0 Or SHFileOp.fAborted Then Exit Sub
MsgBox "Operation Complete", vbInformation, "File Operations"
End Sub
For renaming a folder, here is a one liner
Sub Sample()
Name "C:\Temp2" As "C:\Temp3"
End Sub
Posting this for reference in the future. Using syntax from this answer I fleshed out a class I'd been writing.
I've created a directory manager class in VBA which may be relevant to anyone coming here in the future.
Private m_fso As New FileSystemObject
'
''requires reference to Microsoft Scripting Runtime
Public Function CopyAndRenameDirectory(ByVal p_copyDirectory As String, p_targetDirectory As String, p_newName As String) As Boolean
'example
'p_copyDirectory = "C:\temp\myGoingToBeCopiedDir
'p_targetDirectory = "C:\Temp2"
'p_newName = "AwesomeDir"
'results:
'myGoingToBeCopiedDir --> C:\Temp2\AwesomeDir
CopyAndRenameDirectory = False
p_targetDirectory = p_targetDirectory & "\"
If Not Me.DoesPathExist(p_copyDirectory) Or Not Me.DoesPathExist(p_targetDirectory) Then
Exit Function
End If
On Error GoTo errHandler
m_fso.CopyFolder p_copyDirectory, p_targetDirectory & p_newName, True
On Error GoTo 0
Exit Function
errHandler:
If PRINT_DEBUG Then Debug.Print "Error in CopyAndRenameDirectory: " & Err.Description
Exit Function
End Function
Public Function CopyDirectory(ByVal p_copyDirectory As String, p_targetDirectory As String) As Boolean
'example
'p_copyDirectory = "C:\temp\myGoingToBeCopiedDir
'p_targetDirectory = "C:\Temp2"
'p_newName = ""
'results:
'myGoingToBeCopiedDir --> C:\Temp2\myGoingToBeCopiedDir
CopyDirectory = False
If Not Me.DoesPathExist(p_copyDirectory) Or Not Me.DoesPathExist(p_targetDirectory) Then
Exit Function
End If
p_targetDirectory = p_targetDirectory & "\"
On Error GoTo errHandler
m_fso.CopyFolder p_copyDirectory, p_targetDirectory, True
On Error GoTo 0
Exit Function
errHandler:
If PRINT_DEBUG Then Debug.Print "Error in CopyDirectory: " & Err.Description
Exit Function
End Function
Public Function CreateFolder(ByVal p_path As String) As Boolean
CreateFolder = True
If Me.DoesPathExist(p_path) Then
Exit Function
Else
On Error GoTo errHandler
m_fso.CreateFolder p_path ' could there be any error with this, like if the path is really screwed up?
Exit Function
End If
errHandler:
'MsgBox "A folder could not be created for the following path: " & path & ". Check the path name and try again."
CreateFolder = False
Exit Function
End Function
Public Function DoesPathExist(ByVal p_path As String) As Boolean
DoesPathExist = False
If m_fso.FolderExists(p_path) Then DoesPathExist = True
End Function