I'm using a cmd button to open a popup (single) form that has (2) txtboxes that I want to reflect the information from a single record in the previous (continuous) form. The cmd will
Code on the cmd button:
Private Sub cmdReassign_Click()
On Error GoTo ErrHandler
Dim strOpenArgs As String
strOpenArgs = Me.txtToolGroupID & "," & Me.txtEmployee_Name
DoCmd.OpenForm "popfrmReassignGroupedTools", OpenArgs:=strOpenArgs '
ExitHere:
Exit Sub
ErrHandler:
MsgBox Err.Number & ": " & Err.Description, vbExclamation
Resume ExitHere
End Sub
Code on Form_Open
Private Sub Form_Open(Cancel As Integer)
On Error GoTo ErrHandler
Dim dbs As DAO.Database
Dim rst As DAO.Recordset
Dim strSQL As String
Dim strOpenArgs As String
strOpenArgs = Me.OpenArgs
Set dbs = CurrentDb
strSQL = "SELECT * From qryToolReassignment_Grouped Where ToolGroupID=" & Me.txtToolGroupID & ";"
Set rst = dbs.OpenRecordset(strSQL)
If rst.EOF Then
GoTo ExitHere
End If
With Me
.txtToolCategoryQty = rst.Fields("[Quantity]")
.txtToolLocation = rst.Fields("[Employee Name]")
End With
ExitHere:
On Error Resume Next
Set rst = Nothing
Set dbs = Nothing
Exit Sub
ErrHandler:
MsgBox Err.Number & ": " & Err.Description, vbExclamation
Resume ExitHere
End Sub
I'll admit I borrowed the code from a similar setup where the information was called from a cbo not a cmd. When the popup form opens, only the first record in the query is shown not the record associated to the cmd. Any suggestions. TIA.
Not clear to me what you want. If popup form is BOUND and you want it to open to existing record then use the WHERE argument of OpenForm:
DoCmd.OpenForm "popfrmReassignGroupedTools", , , "ToolGroupID=" & Me.txtToolGroupID
If txtToolGroupID is on the continuous form then the popup form Open event cannot reference it with Me alias.
If you want to pass multiple values with OpenArgs, will have to use string manipulation functions to parse the data elements.
If Not IsNull(Me.OpenArgs) Then
intID = Left(Me.OpenArgs, InStr(Me.OpenArgs, ",")-1)
strEmp = Mid(Me.OpenArgs, InStr(Me.OpenArgs, ",")+1)
End If
Instead of all that code to declare and open recordset object, a DLookup() might serve.
Related
I've got a small Access program that looks up files names from a query ("qryImagesToRename"), goes through a loop and renames them. However, if an image already exists with the same name Access wants to rename it to, I receive
error 58 - File Already Exists
How do I ignore this error and continue with the loop? This my code:
Private Sub Command10_Click()
On Error GoTo Command10_Click_Error
Dim rs As DAO.Recordset
Dim db As DAO.Database
Dim strSQL As String
DoCmd.Hourglass True
Set db = CurrentDb
strSQL = "select * from qryImagesToRename"
Set rs = db.OpenRecordset(strSQL)
Do While Not rs.EOF
Name rs.Fields("From").Value As rs.Fields("To").Value
rs.MoveNext
Loop
DoCmd.Hourglass False
MsgBox "All matching files renamed"
On Error GoTo 0
Exit Sub
Command10_Click_Error:
MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure Command10_Click of VBA Document Form_frmRename - Please take a screenshot and email xxxxxx#xxxxxxx.com"
End Sub
If you are certain that you can ignore the error then you could use On Error Resume Next to ignore it and continue processing. Ensure that you add On Error Goto 0 as soon as you can, to reinstate the normal error processing.
On Error Resume Next
Do While Not rs.EOF
Name rs.Fields("From").Value As rs.Fields("To").Value
rs.MoveNext
Loop
On Error GoTo 0
This is most often a poor practice, but can be used if there is certainty about behaviour.
A better practice would be to check if the file already exists using Dir (or FileSystemObject) and skip it. Discussed here
Two particular solutions come to mind. The first, is in-line logic to check for the existing file, and skip that item, and the second is to put a case statement in the error handler. I have outlined the code below to have both options. I hope it helps.
Private Sub Command10_Click()
On Error GoTo Command10_Click_Error
Dim rs As DAO.Recordset
Dim db As DAO.Database
Dim strSQL As String
Dim fso as New FileSystemObject
DoCmd.Hourglass True
Set db = CurrentDb
strSQL = "select * from qryImagesToRename"
Set rs = db.OpenRecordset(strSQL)
Do While Not rs.EOF 'if you want to use the logic inline, use the check below
If fso.fileexists(rs.Fields("To").value) = false Then
Name rs.Fields("From").Value As rs.Fields("To").Value
End If
NextRecord: 'if you want to use the goto statement, use this
rs.MoveNext
Loop
DoCmd.Hourglass False
MsgBox "All matching files renamed"
On Error GoTo 0
Exit Sub
Command10_Click_Error:
Select case Err.number
Case 58
GoTo NextRecord
Case Else
MsgBox "Error " & Err.Number & " (" & Err.Description & ") in procedure Command10_Click of VBA Document Form_frmRename - Please take a screenshot and email xxxxxx#xxxxxxx.com"
End select
End Sub
In access 2013, I'm using a form (called "Table1") linked to a table that has an attachment field that I'm adding a scanned document (bmp) to. There are two textboxes that I use to name the scanned document on the form. Everything works if I input the record then hit save and then click my button (called testButton), but if I don't hit save, the attachment saves to the last record or a few records back. I'm pretty sure it's a saving issue, because when I try to scan and attach after the computer has been dormant, it works just fine, I'm guessing autosave. However, if I'm trying to scan multiple records back to back, the attachment goes to the previous record if I don't hit save on the ribbon. I've tried placing
DoCmd.Save acForm, "Table1"
or
If Me.Dirty Then
Me.Dirty = False
MsgBox ("File Saved")
End If
or even
DoCmd.RunCommand acCmdSaveRecord
at different points in the code to no avail. The DoCmd functions save the record, but start the recordset at the first record, not the one I'm currently inputting. So instead of attaching to the second to last record, it attaches to the first record.
My goal is to be able to hit the button and it work perfectly without having to hit save. I even looked for a code that does exactly what the save button on the ribbon does to no avail.
Here is the current code I'm using.
Option Compare Database
Dim FileLocation As String
Dim diagFile As FileDialog
Private Sub testButton_Click()
'DoCmd.Save acForm, "Table1" (Commented out, because it's not working)
Dim db As DAO.Database
Dim rsParent As DAO.Recordset2
Dim rsChild As DAO.Recordset2
If Me.Dirty Then
Me.Dirty = False
MsgBox ("File Saved")
End If
Me.testBox = Me.Payment & Me.Merchant ' I use this to see the input on screen
ScanImage
AttachImage
End Sub
Private Sub ScanImage()
'This method works, it's the AttachImage that's causing issues.
Set diagFile = Application.FileDialog(msoFileDialogSaveAs)
diagFile.Title = "Save Bitmap File As..."
diagFile.InitialFileName = Me.Payment & " " & Me.Merchant & ".bmp"
diagFile.Show
FileLocation = diagFile.SelectedItems(1)
Dim scanDiag As New WIA.CommonDialog
Dim image As WIA.ImageFile
Set image = scanDiag.ShowAcquireImage(ScannerDeviceType)
image.SaveFile FileLocation
MsgBox ("File Saved")
' MsgBox (CurrentRecord) I used this to see on screen the record I'm inputing
End Sub
Private Sub AttachImage()
MsgBox ("Step 1 attaching") ' I use this and all the MsgBoxes to see where in the code the procedure is.
'MsgBox ("Step 2 attaching")
On Error GoTo Err_AddImage
Set db = CurrentDb
Set rsParent = Me.Recordset
rsParent.Edit
Set rsChild = rsParent.Fields("Receipt").Value
'MsgBox "Nombre el archivo: " & rsChild("FileName").Value
'MsgBox "Tipo de archivo: " & rsChild.Fields("FileType").Value
'MsgBox "Data del archivo: " & rsChild.Fields("FileData").Value
'Do Until rsChild.EOF
' For Each fld In rsChild.Fields
' Debug.Print fld
' Next fld
' rsChild.MoveNext
' Loop
'MsgBox ("Step 3 attaching")
rsChild.AddNew
rsChild.Fields("FileData").LoadFromFile ("C:\Users\omoawotona\Desktop\Receipt Clone\" & Me.Payment & " " & Me.Merchant & ".bmp")
rsChild.Update
rsParent.Update
'MsgBox ("Step 4 attaching")
Me.Refresh
'MsgBox ("Step 5 attaching")
'MsgBox ("Attachment done")
Exit_AddImage:
Set rsChild = Nothing
Set rsParent = Nothing
Exit Sub
Err_AddImage:
If Err = 3820 Then
MsgBox ("File already part of the multi-valued field!")
Me.Refresh
Resume Next
Else
MsgBox "Some Other Error occured!", Err.Number, Err.Description
Resume Exit_AddImage
End If
End Sub
I edited code by referring to How do I access the selected rows in Access?. But I got runtime error of 3021 at RS.Move F.SelTop - 1 with my code even though m_SelNumRecs is not zero. I am not sure if I have to add additional code to my code.
I have a form including a subform of frm_SubPerson. I select record(s) on the frm_SubPerson and want to conver the record(s) into pdf.
Public m_SelNumRecs As Long
Public m_SelTopRec As Long
Public m_CurrentRec As Long
Private Sub cmdConvert()
Dim mSelTop As Long
Dim mSelHeight As Long
Dim F As Form
Dim RS As Recordset
Dim filePath As String
Dim i As Integer
' Get the form and its recordset.
Set F = Me.frm_SubPerson.Form
Set RS = F.RecordsetClone
If m_SelNumRecs = 0 Then
MsgBox "no record is selected."
Exit Sub
End If
' Move to the first selected record.
RS.Move F.SelTop - 1 '3021 error
For i = 1 To m_SelNumRecs
DoCmd.OpenReport "report_Person", acViewPreview, , "report_Person.chName=" & "'" & RS!chName.Value & "'"
filePath = "D:\report_Person\" & "report_Person" & RS!chName & "_" & RS!chNum & "_" & RS!reYear.Value & "Year" & RS!reMonth & "Month" & ".pdf"
DoCmd.OutputTo acOutputReport, "", acFormatPDF, filePath
DoCmd.Close acReport, "report_Person"
RS.MoveNext
Next i
RS.Close
Set RS = Nothing
End Sub
Private Sub frm_SubPerson_Exit(Cancel As Integer)
With frm_SubPerson.Form
m_SelNumRecs = .SelHeight
m_SelTopRec = .SelTop
m_CurrentRec = .CurrentRecord
End With
End Sub
I have an access report that updates 4 image controls based on a table that is sourcing images from a directory. The report generates a page per record, however the image controls are not changing after page 1 (just showing same images for all the other pages). Appartently, the code worked fine on Windows XP and now does not work on Windows 7 OS (both used Office 07). Here is the code:
Private Sub Report_Current()
UpdateImages
End Sub
Private Sub Report_Load()
UpdateImages
End Sub
Private Sub Report_Page()
UpdateImages
End Sub
Private Sub UpdateImages()
On Error GoTo errHandler
Dim RS As DAO.Recordset
Set RS = CurrentDb.OpenRecordset("SELECT Image_Loc, Image_Name FROM HH_Media WHERE InspectionID = " & CInt(Me.InspectionID.Value) & " ORDER BY MediaID ASC")
If Not RS.BOF And Not RS.EOF Then
Dim i As Integer
For i = 1 To 4
If Not RS.EOF Then
Dim pictureCtrl As Image
Set pictureCtrl = GetControl("Image" & i)
Dim strImage As String
strImage = RS.Fields("Image_Loc").Value & "\" & RS.Fields("Image_Name").Value
If Not pictureCtrl Is Nothing Then
If FileExists(strImage) Then
pictureCtrl.Picture = strImage
SetLabel "lblImage" & i, RS.Fields("Image_Name").Value
Else
pictureCtrl.Picture = ""
SetLabel "lblImage" & i, "Does not exist"
End If
End If
RS.MoveNext
Else
Exit For
End If
Next
End If
RS.Close
Set RS = Nothing
Exit Sub
errHandler:
MsgBox "An error occurred while updating the form display." & vbNewLine & Err.Description, vbApplicationModal + vbCritical + vbDefaultButton1 + vbOKOnly, Me.Name
Resume Next
End Sub
The images do exist in the directory that are referenced in the table. Any ideas of what is missing?
Thank You
Whenever I need to do some dynamic content I always use the [section]_Format event - so if your controls are on the Detail section then:
Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
If FormatCount = 1 then 'only need to do this once per record
UpdateImages
Endif
End Sub
I've never seen the GetControl method, and I don't have a lot of experience using the Image control, but it seems like that the Dim statement should read more like:
Dim pictureCtrl as Control
Set pictureCtrl = Me.Controls("Image" & i)
I would insert a break and verify that
strImage = RS.Fields("Image_Loc").Value & "\" & RS.Fields("Image_Name").Value
is returning values you expect. You can also shorten these to:
strImage = rs!Image_Loc & "\" & rs!Image_Name
sometimes Access doesn't like the added ".value" as this is already the default return.
I'm executing a query like this
select field from table;
In that query, there is a loop running on many tables. So, if the field is not present in a table I get a
Runtime Error 3061
How can I by pass this error such as that on this error flow should go to another point?
This is the code I have recently after going through this forum.
Option Explicit
Private Sub UpdateNulls()
Dim rs2 As DAO.Recordset
Dim tdf As DAO.TableDef
Dim db As Database
Dim varii As Variant, strField As String
Dim strsql As String, strsql2 As String, strsql3 As String
Dim astrFields As Variant
Dim intIx As Integer
Dim field As Variant
Dim astrvalidcodes As Variant
Dim found As Boolean
Dim v As Variant
Open "C:\Documents and Settings\Desktop\testfile.txt" For Input As #1
varii = ""
Do While Not EOF(1)
Line Input #1, strField
varii = varii & "," & strField
Loop
Close #1
astrFields = Split(varii, ",") 'Element 0 empty
For intIx = 1 To UBound(astrFields)
'Function ListFieldDescriptions()
Dim cn As New ADODB.Connection, cn2 As New ADODB.Connection
Dim rs As ADODB.Recordset, rs3 As ADODB.Recordset
Dim connString As String
Dim SelectFieldName
Set cn = CurrentProject.Connection
SelectFieldName = astrFields(intIx)
Set rs = cn.OpenSchema(adSchemaColumns, Array(Empty, Empty, Empty, SelectFieldName))
'Show the tables that have been selected '
While Not rs.EOF
'Exclude MS system tables '
If Left(rs!Table_Name, 4) <> "MSys" Then
strsql = "Select t.* From [" & rs!Table_Name & "] t Inner Join 01UMWELT On t.fall = [01UMWELT].fall Where [01UMWELT].Status = 4"
End If
Set rs3 = CurrentDb.OpenRecordset(strsql)
'End Function
strsql2 = "SELECT label.validcode FROM variablen s INNER JOIN label ON s.id=label.variablenid WHERE varname='" & astrFields(intIx) & "'"
Set db = OpenDatabase("C:\Documents and Settings\Desktop\Codebook.mdb")
Set rs2 = db.OpenRecordset(strsql2)
With rs2
.MoveLast
.MoveFirst
astrvalidcodes = rs2.GetRows(.RecordCount)
.Close '
End With
With rs3
.MoveFirst
While Not rs3.EOF
found = False
For Each v In astrvalidcodes
If v = .Fields(0) Then
found = True
Debug.Print .Fields(0)
Debug.Print .Fields(1)
Exit For
End If
Next
If Not found Then
msgbox "xxxxxxxxxxxxxxxx"
End If
End If
.MoveNext
Wend
End With
On Error GoTo 0 'End of special handling
Wend
Next intIx
End Sub
I'm getting a
Type Mismatch Runtime Error
in Set rs3 = CurrentDb.OpenRecordset(strsql)
I guess I'm mixing up ado and dao but I'm not certainly sure where it is.
Use the On Error statement that VBA supplies:
Sub TableTest
On Error Goto TableTest_Error
' ...code that can fail... '
Exit Sub
:TableTest_Error
If Err.Number = 3061 Then
Err.Clear()
DoSomething()
Else
MsgBox Err.Description ' or whatever you find appropriate '
End If
End Sub
Alternatively, you can switch off automatic error handling (e.g. breaking execution and displaying an error message) on a line-by-line basis:
Sub TableTest
' ... fail-safe code ... '
On Error Resume Next
' ...code that can fail... '
If Err.Number = 3061 Then
Err.Clear()
DoSomething()
Else
MsgBox Err.Description
End If
On Error Goto 0
' ...mode fail-safe code... '
End Sub
There are these statements available:
On Error Resume Next switches off VBA-integrated error handling (message box etc.) completely, execution simply resumes on the next line. Be sure to check for an error very early after you've used that, as a dangling error can disrupt the normal execution flow. Clear the error as soon as you caught it to prevent that.
On Error Goto <Jump Label> resumes execution at a given label, primarily used for per-function error handlers that catch all sorts of errors.
On Error Goto <Line Number> resumes at a given line number. Stay away from that, it's not useful, even dangerous.
On Error Goto 0 it's close cousin. Reinstates the VBA integrated error management (message box etc.)
EDIT
From the edited qestion, this is my proposal to solve your problem.
For Each FieldName In FieldNames ' assuming you have some looping construct here '
strsql3 = "SELECT " & FieldName & " FROM table"
On Error Resume Next
Set rs3 = CurrentDb.OpenRecordset(strsql3)
If Err.Number = 3061 Then
' Do nothing. We dont care about this error '
Err.Clear
Else
MsgBox "Uncaught error number " & Err.Number & " (" & Err.Description & ")"
Err.Clear
End If
On Error GoTo 0
Next FieldName
Be sure to clear the error in any case before you go on with a loop in the same Sub or Function. As I said, a dangling error causes code flow to become unexpected!
Rather than trapping the error, why not use the TableDefs to check for the field or use a mixture of ADO and DAO? ADO Schemas can provide a list of tables that contain the required field:
Function ListTablesContainingField()
Dim cn As New ADODB.Connection, cn2 As New ADODB.Connection
Dim rs As ADODB.Recordset, rs2 As ADODB.Recordset
Dim connString As String
Dim SelectFieldName
Set cn = CurrentProject.Connection
SelectFieldName = "Fall" 'For tksy '
'Get names of all tables that have a column called 'ID' '
Set rs = cn.OpenSchema(adSchemaColumns, _
Array(Empty, Empty, Empty, SelectFieldName))
'Show the tables that have been selected '
While Not rs.EOF
'Exclude MS system tables '
If Left(rs!Table_Name, 4) <> "MSys" Then
' Edit for tksy, who is using more than one forum '
If tdf.Name = "01UMWELT" Then
strSQL = "Select * From 01UMWELT Where Status = 5"
Else
strSQL = "Select a.* From [" & rs!Table_Name _
& "] a Inner Join 01UMWELT On a.fall = 01UMWELT.fall " _
& "Where 01UMWELT.Status = 5"
End If
Set rs2 = CurrentDb.OpenRecordset(strSQL)
Do While Not rs2.EOF
For i = 0 To rs2.Fields.Count - 1
If IsNull(rs2.Fields(i)) Then
rs2.Edit
rs2.Fields(i) = 111111
rs2.Update
End If
Next
rs2.MoveNext
Loop
End If
rs.MoveNext
Wend
rs.Close
Set cn = Nothing
End Function
Try this:
On Error Resume Next ' If an error occurs, move to next statement.
...statement that tries the select...
If (Err <> 0) Then
...act on error, or simply ignore if necessary...
End If
On Error Goto 0 ' Reset error handling to previous state.