VBA Access multiple replace - vba

I have a table master with a memo field. This fileld content many abreviation of full text. The full text is on another table call nomemclature.
I want to make a multiple replace from the nomemclature table to the master table with the correspondant field.
I also have some problem with the abreviation field. The field has many error like space ans other caractere that l want not to replace.
How can i do the thing ?

You can use the code below. Use it as in the Test procedure. In the first recordset, supply the one field you want to process. In the secord recordset, supply the two fields for find and replace.
Public Sub Test()
Dim oRSetToProcess As Recordset
Dim oRSetFindReplace As Recordset
DoCmd.SetWarnings False
Set oRSetToProcess = CurrentDb.OpenRecordset("SELECT [MemoField] FROM [tblData];")
Set oRSetFindReplace = CurrentDb.OpenRecordset("SELECT [Find],[Replace] FROM [tblFindReplace];")
BulkReplace oRSetToProcess, oRSetFindReplace
oRSetToProcess.close
oRSetFindReplace.close
Set oRSetToProcess = Nothing
Set oRSetFindReplace = Nothing
DoCmd.SetWarnings True
End Sub
Public Sub BulkReplace(oRSetToProcess As Recordset, oRSetFindReplace As Recordset)
Dim sTempString As String
oRSetToProcess.MoveFirst
Do Until oRSetToProcess.EOF
sTempString = oRSetToProcess(0)
oRSetFindReplace.MoveFirst
Do Until oRSetFindReplace.EOF
sTempString = Replace(sTempString, oRSetFindReplace(0), oRSetFindReplace(1))
oRSetFindReplace.MoveNext
Loop
With oRSetToProcess
.Edit
.Fields(0) = sTempString
.Update
.MoveNext
End With
Loop
End Sub

Related

populating multiple fields in subform using combobox and AfterUpdate Event Prodcedure

I am creating a set of Access database form for entering vegetation data into a linked SQL Server data base. For one protocol, I have created a form 'frmLPI' for entering data from a vegetation monitoring method called Line-Point-Intercept. It is a form with a subform within it called 'frmLPIDetail' where individual counts of plant species get recorded. The main form has three unbound controls: [TransectOID], [DataRec], and [DataObs]. TransectOID is a unique id for each time we ran protocol. For each TransectOID, there are 30 locations where we sampled vegetation these have a hidden unique id in the subform called LPI_OID. The subform is linked to the main form by TransectOID. I want my users to be able to click the unbound [DataRec] and [DataObs] comboboxes in the main form, and have the corresponding fields in the subform autopopulate for all 30 records. I have figure out how to accomplish this for record in the subform but can't figure out how to do it for 30 records for each value of TransectOID in the Main form. Below is a screenshot of my form to help you visualize what I am after:
And here is the code I have come up with to get one record to autopopulate
Private Sub Form_Load()
Me.TransectOID = Me.OpenArgs
End Sub
Private Sub Form_Deactivate()
DoCmd.RunCommand acCmdSaveRecord
End Sub
Private Sub DataObs_AfterUpdate()
Me!frmLPIDetail.Form!Data_observer = Me!DataObs
Me.Dirty = False
End Sub
Private Sub DataRec_AfterUpdate()
Me!frmLPIDetail.Form!Data_recorder = Me!DataRec
Me.Dirty = False
End Sub
Any suggestions would be much appreciated
Since inserting multiple records at a time is desirable your question has been asked before but I couldn't find an answer that was particularly helpful so I will provide a more general answer than you asked for.
Access doesn't provide default forms for inserting multiple records. You have to code that yourself but the process is always pretty much the same.
figure out a normalized table structure for your data
figure what data you need to collect from the user for the multiple insert
add a button to the form and put the vba for the multiple insert in the click event
so here is 1 normalized table structure that might fit your data:
Since I don't know where TransectionOID is coming from we let Access provide TransectionID as the primary key and assume TransectionOID is entered on another form. All the other information of interest is in the TransectionDetails table and there is no need to write a query to gather all the variables we will need into our forms record source to finish step 2. To get a jumpstart I selected the TransactionDetails table and used the create form wizard to make a tabular style form.
To finish step 2 we put controls in the header to collect the information from the user we will need and the start editing the form for user friendliness. For instance I delete the checkbox for TransectionDetailID in the details section and replace every other control with comboboxes. I normally replace the circled record selectors with comboboxes as well but here that may be confusing so I leave the record selectors to provide some search functionality. The final form looks like:
Finally, for step 3 we add the vba for the click event
Private Sub cmdInsert_Click()
Dim db As Database
Dim rs As Recordset 'using recordset because lower error rate than using sql strings
Set db = CurrentDb
Set rs = db.OpenRecordset("TransectionDetails")
Dim L As Integer
Dim S As Integer
If Not Me.lstLocations.ListCount = 0 Then 'if no locations are selected no records can be inserted
For L = 0 To Me.lstLocations.ListCount 'simple multiselect listbox version matters for the vba code
If Me.lstLocations.Selected(L) = True Then
For S = 0 To Me.lstSpecies.ListCount
If Me.lstSpecies.Selected(S) = True Then
rs.AddNew
rs!TransectionID = Me.cmbTransectionID
rs!Data_observer = Me.cmbData_observer
rs!Data_recorder = Me.cmbData_recorder
rs!TransectLocation = Me.lstLocations.Column(0, L) 'column gives you access to values in the listbox
rs!SpeciesID = Me.lstSpecies.Column(0, S)
If Not IsNull(Me.chkDead) Then 'chkDead is a triple value checkbox, this both avoids setting Dead to null and shows how to handle when the user doesn't set all controls
rs!Dead = Me.chkDead
End If 'chkdead
rs.Update
End If 'lstspecies selected
Next S
End If
Next L
End If
Me.Detail.Visible = True 'quick and dirty bit of style (detail starts invisible)
Me.Filter = "TransectionID = " & Me.cmbTransectionID 'more quick and dirty style filter to focus on inserted records
Me.FilterOn = True
'clean up
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
Private Sub cmdSelectAllLocations_Click()
Dim i As Integer
For i = 0 To Me.lstLocations.ListCount
Me.lstLocations.Selected(i) = True
Next
End Sub
Private Sub cmdSelectAllSpecies_Click()
Dim i As Integer
For i = 0 To Me.lstSpecies.ListCount
Me.lstSpecies.Selected(i) = True
Next
End Sub
Private Sub cmdSelectNoLocations_Click()
Dim i As Integer
For i = 0 To Me.lstLocations.ListCount
Me.lstLocations.Selected(i) = False
Next
End Sub
Private Sub cmdSelectNoSpecies_Click()
Dim i As Integer
For i = 0 To Me.lstSpecies.ListCount
Me.lstSpecies.Selected(i) = False
Next
End Sub
While Mazoula's answer is far more elegant, I discovered a quick and dirty way to accomplish what I was after using a While loop. Below is my code:
Private Sub Form_Load()
Me.TransectOID = Me.OpenArgs
End Sub
Private Sub Form_Deactivate()
DoCmd.RunCommand acCmdSaveRecord
End Sub
Private Sub DataObs_AfterUpdate()
Dim rs As DAO.Recordset
Set rs = Me!frmLPIDetail.Form.RecordsetClone
rs.MoveLast
rs.MoveFirst
While Not rs.EOF
rs.Edit
rs!Data_observer.Value = Me.DataObs.Value
rs.Update
rs.MoveNext
Wend
rs.Close
Set rs = Nothing
Me.Dirty = False
End Sub
Private Sub DataRec_AfterUpdate()
Dim rs As DAO.Recordset
Set rs = Me!frmLPIDetail.Form.RecordsetClone
rs.MoveLast
rs.MoveFirst
While Not rs.EOF
rs.Edit
rs!Data_recorder.Value = Me.DataRec.Value
rs.Update
rs.MoveNext
Wend
rs.Close
Set rs = Nothing
Me.Dirty = False
End Sub

MS Access: How can I return all table and field names with in that table that have the field format 'hyperlink' via SQL or VBA?

I have multiple tables, within some of those tables I have fields that are formatted as hyperlink. I want to return the tables names that contain hyperlink formatted fields and the subsequent field names?
I am trying to do this within VBA, I'm thinking an SQL call within VBA.
You can loop through every tableDef/Table in the database, but it gets a little hairy since hyperlinks are an attribute on a memo field type. The Attributes property of Access objects are a bitmask, so when checking to see if a particular attribute is set, you have to check if that attributes bit is set in the bitmask.
Sub ListTablesWithHyperlinks()
Dim tdf As TableDef
Dim fld As Field
Dim tdfPrint As Boolean
'Loop through all tables
For Each tdf In CurrentDb.TableDefs
'Set flag to false
tdfPrint = False
'Loop through all fields
For Each fld In tdf.Fields
'Test if column has an attribute of `dbHyperlinkField`
If (fld.Attributes And dbHyperlinkField) = dbHyperlinkField Then
'Set the flag and exit the loop
tdfPrint = True: Exit For
End If
Next fld
'If the flag was set to true, then iterate fields again and print out
If tdfPrint Then
For Each fld In tdf.Fields
'Print out tablename, column ordinal, and column name
Debug.Print tdf.Name, fld.OrdinalPosition, fld.Name
Next fld
End If
Next tdf
End Sub

Create a new record from existing one with changes to two fields in Access dB [duplicate]

Background:
I have a subform (datasheet) I update using a datasheet checkbox afterupdate event:
I clone the clicked record & Insert into the referenced table via an Insert Query
I modify the original record to differentiate from the Inserted record via an Update Query
To avoid RecordLock complaints, I have inserted: SendKeys "+{Enter}", True after each of the above to save the updates - is there a better way to do this??
Next I need to requery the subform to display the newly inserted record AND use a bookmark (?) to retain the cursor position of the original record (inserted record will be adjacent). Subform datasheet recordset is based on a query.
Question:
From within the subform's afterupdate event, using Forms![ParentForm].[SubForm].Form.Requery does not produce an error, but does open the code window with the line highlighted in Yellow.
Next attempt, from within the subform's afterupdate event, I have attempted to set focus to a control on the ParentForm BEFORE using Forms![ParentForm].[SubForm].Form.Requery, but I get a similar ~silent error~ as noted above.
What is the proper way to REQUERY a subform from within the same subform?
Thanks!
You are making it way too hard for yourself. Here is how to copy a record from a button click. No locks, no queries, and auto update of the form:
Private Sub btnCopy_Click()
Dim rstSource As DAO.Recordset
Dim rstInsert As DAO.Recordset
Dim fld As DAO.Field
If Me.NewRecord = True Then Exit Sub
Set rstInsert = Me.RecordsetClone
Set rstSource = rstInsert.Clone
With rstSource
If .RecordCount > 0 Then
' Go to the current record.
.Bookmark = Me.Bookmark
With rstInsert
.AddNew
For Each fld In rstSource.Fields
With fld
If .Attributes And dbAutoIncrField Then
' Skip Autonumber or GUID field.
ElseIf .Name = "SomeFieldToHandle" Then
rstInsert.Fields(.Name).Value = SomeSpecialValue
ElseIf .Name = "SomeOtherFieldToHandle" Then
rstInsert.Fields(.Name).Value = SomeOtherSpecialValue
ElseIf .Name = "SomeFieldToSkip" Then
' Leave empty or with default value.
ElseIf .Name = "SomeFieldToBlank" Then
rstInsert.Fields(.Name).Value = Null
Else
' Copy field content.
rstInsert.Fields(.Name).Value = .Value
End If
End With
Next
.Update
' Go to the new record and sync form.
.MoveLast
Me.Bookmark = .Bookmark
.Close
End With
End If
.Close
End With
Set rstInsert = Nothing
Set rstSource = Nothing
End Sub
If the button is placed on the parent form, replace Me with:
Me!NameOfYourSubformControl.Form
Between AddNew and Update you can modify and insert code to adjust the value of some fields that should not just be copied.

Query error on a recordset.update vba line

I am trying to print multiple labels for multiple records. The number of labels is consistent for any one run of the label report and all labels for the same record need to be together on the printed sheet. Parameters are entered on TakeNoticeForm and once a button is clicked a recordset, rsQuery, is created with TakeNoticeLabelQuery. Another recordset is created, rsTable, based on a table, TemporaryTNLabels. This table is a copy of my main table, Certificates, without data. I'm using nested For loops to parse through the query results and add "x" copies of said record into the temp table, which will then be used to print the labels. Once the labels are printed the data will be cleared from the temp table for use again later.
Everything I have so far appears to work until I actually start adding data to my temp table. I get Error 3991 - "The query failed to execute because the identifier '[Certificates].[TownshipID]' could not be found" and it points to .Update. [TownshipID] is a lookup field in the Certificates table that was the original for TemporaryTNLabels. I tried to keep the copy intact for possible reuse with other reports but I don't need that field for this report so deleted the lookup field from the temp table to hopefully solve the problem. TakeNoticeLabelQuery is actually a copy of another query, TakeNoticeQuery, that did reference Township information. Again, I was hoping to reuse objects but made a copy and only kept what I needed, which has no reference to TownshipID.
After stripping everything unnecessary away, I can't figure out why it's still trying to find [TownshipID]. I'm still trying to wrap my head around recordsets so wondering if the problem is actually elsewhere, buty I'm confused as to how this error is even remotely related to my code. Any help is appreciated. The SQL for the query and code for generating label data are below.
SELECT Certificates.DatabaseID, Certificates.CertCounty, Certificates.TaxYear, Certificates.ParcelNumber, Certificates.MailToFirstName, Certificates.MailToLastName, Certificates.MailToAlso, Certificates.MailToCity, Certificates.MailToState, Certificates.MailToZip
FROM Counties INNER JOIN Certificates ON Counties.ID = Certificates.CertCounty
WHERE (((Certificates.DatabaseID) Between ([Forms]![TakeNoticeForm]![FirstDBTextbox]) And ([Forms]![TakeNoticeForm]![LastDBTextbox])) AND ((Certificates.CertCounty) Like [Forms]![TakeNoticeForm]![CountyCombobox] & '*') AND ((Certificates.TaxYear) Like [Forms]![TakeNoticeForm]![TaxYearTextbox] & '*')) OR (((Certificates.CertCounty) Like [Forms]![TakeNoticeForm]![CountyCombobox] & '*') AND ((Certificates.TaxYear) Like [Forms]![TakeNoticeForm]![TaxYearTextbox] & '*') AND ((IsNull([Forms]![TakeNoticeForm]![FirstDBTextbox]))<>False) AND ((IsNull([Forms]![TakeNoticeForm]![LastDBTextbox]))<>False));
Option Compare Database
Option Explicit
Private Sub TNLabelPreviewButton_Click()
Dim iTab As Integer
Dim iLabel As Integer
Dim numLabels As Integer
Dim totalRecords As Long
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim rsTable As DAO.Recordset
Dim rsQuery As DAO.Recordset
' Set query definition for creating recordset
Set db = CurrentDb()
Set qdf = db.QueryDefs("TakeNoticeLabelQuery")
If CurrentProject.AllForms("TakeNoticeForm").IsLoaded Then
qdf.Parameters("[Forms]![TakeNoticeForm]![FirstDBTextbox]") = [Forms]![TakeNoticeForm]![FirstDBTextbox]
qdf.Parameters("[Forms]![TakeNoticeForm]![LastDBTextbox]") = [Forms]![TakeNoticeForm]![LastDBTextbox]
qdf.Parameters("[Forms]![TakeNoticeForm]![CountyCombobox]") = [Forms]![TakeNoticeForm]![CountyCombobox]
qdf.Parameters("[Forms]![TakeNoticeForm]![TaxYearTextbox]") = [Forms]![TakeNoticeForm]![TaxYearTextbox]
' qdf.Parameters("[Forms]![TakeNoticeForm]![TakeNoticeDateTextbox]") = [Forms]![TakeNoticeForm]![TakeNoticeDateTextbox]
Else
qdf.Parameters("[Forms]![TakeNoticeForm]![FirstDBTextbox]") = ""
qdf.Parameters("[Forms]![TakeNoticeForm]![LastDBTextbox]") = ""
qdf.Parameters("[Forms]![TakeNoticeForm]![CountyCombobox]") = ""
qdf.Parameters("[Forms]![TakeNoticeForm]![TaxYearTextbox]") = ""
' qdf.Parameters("[Forms]![TakeNoticeForm]![TakeNoticeDateTextbox]") = CStr(Date)
End If
Set rsQuery = qdf.OpenRecordset
rsQuery.MoveLast
totalRecords = rsQuery.RecordCount
'Close and delete records from TemporaryTNLabels table.
DoCmd.SetWarnings False
DoCmd.Close acTable, "TemporaryTNLabels"
DoCmd.RunSQL "DELETE FROM [TemporaryTNLabels]"
DoCmd.SetWarnings True
numLabels = Me.NumLabelsTextbox
MsgBox numLabels & " labels"
'Open a table-type Recordset
Set rsTable = db.OpenRecordset("TemporaryTNLabels", dbOpenTable)
rsQuery.MoveFirst
With rsTable
For iTab = 1 To totalRecords
For iLabel = 1 To numLabels
Debug.Print rsQuery!DatabaseID
.AddNew
!ParcelNumber = rsQuery!ParcelNumber
.Update ' <-------------------------This is where the error points.
.Bookmark = .LastModified
Next iLabel
rsQuery.MoveNext
Next iTab
End With
' DoCmd.OpenReport ReportName:="TakeNoticeLabelReport", View:=acViewPreview
rsTable.Close
Set rsQuery = Nothing
Set qdf = Nothing
Set db = Nothing
End Sub
This is why I stopped using lookup fields :-( I would delete the table TemporaryTNLabels or rename it to TemporaryTNLabels_OLD. Then recreate the table TemporaryTNLabels from scratch with only one field ParcelNumber, and start from there.

Extract and display data from access table using VBA

I have a function to extract and then display a recordset in a listbox.
I only get one field in my listbox.
Is there a way I can display the whole column "Caption" (several fields) in the listbox?
Function GetCaption() As String
Dim db As Database
Dim rst As DAO.Recordset
Dim SQL As String
Dim LCaption As String
Set db = CurrentDb()
SQL = "SELECT Caption FROM tblMainMenu"
Set rst = db.OpenRecordset(SQL)
If rst.EOF = False Then
LCaption = rst("Caption")
Else
LCaption = "Not found"
End If
rst.Close
Set rst = Nothing
GetCaption = LCaption
End Function
Private Sub btnGetCaption1_Click()
LstBx.RowSourceType = "Value List"
LstBx.RowSource = GetCaption
End Sub
Private Sub Form_Load()
LstBx.RowSource = ""
btnGetCaption1.Caption = DLookup("ReportID", "tblMainMenu", "ReportID = 1")
End Sub
I'm not sure how well I understand your goal. But if you want the list box to contain tblMainMenu.Caption values, one per list box row, you can use the query as its Record Source.
With the form open in Design View, open the list box's property sheet, and select the Data tab. Then choose "Table/Query" for Row Source Type. Add this SQL for the Row Source property.
SELECT [Caption] FROM tblMainMenu
Then select the Format tab, and enter 1 for the Column Count property.
Finally switch to Form View and tell us whether that gives you what you want, or how it differs from what you want.