Opening a Specific Record in an Access Form From Excel - excel

I'm writing a macro that will open an Access Database, open a form and display a specific record based on the contents of the ActiveCell. I have it mostly working, but the problem I'm having is that it opens a form that only contains the one record, so the arrow buttons at the bottom don't go to other records. Is there a way to open the form with all the records and then move to then one i want to show? I suspect it has to do with the search box at the bottom of the form, but I can't find any info about it on the internet.
Form opened by Macro:
Form opened manually:
Sub File_open()
Dim app as Object
Dim search As String: search = ActiveCell.Value
If (ActiveCell.Font.ColorIndex = 3) And (InStr(ActiveCell.Value, "-") <> 0) Then
'Open NCR Record
Set app = CreateObject("Access.Application")
app.Visible = True
app.OpenCurrentDatabase ("Z:\Quality\NCR Database\NCR Databse " & "20" & Left(ActiveCell.Value, 2) & "0101.accdb")
app.DoCmd.OpenForm "Issue Details", , , "[ID]=" & Abs(Replace(Right(search, 4), "-", ""))
Set app = Nothing
Exit Sub
End If
Msbox ("NCR Not Found.")
End Sub
UPDATE:
I've noticed that users of this database have been sloppy and the [ID] of the records don't line up with the number I get from my Abs(Replace(Right(search, 4), "-", "")) expression. I want to look at a textbox named [Title] whose control source is a field called [NCR Number] and use the search variable as is to find the record. I changed my code and now I just get a input box that is completely baffling to me:
app.DoCmd.OpenForm "Issue Details", WhereCondition:="[Title]=" & search

You're showing the form with DoCmd.OpenForm:
expression.OpenForm (FormName, View, FilterName, WhereCondition, DataMode, WindowMode, OpenArgs)
For FormName you're passing "Issue Details", skipping View and FilterName parameters, and then you provide a WhereCondition argument:
app.DoCmd.OpenForm "Issue Details", , , "[ID]=" & Abs(Replace(Right(search, 4), "-", ""))
That "[ID]=" & Abs(Replace(Right(search, 4), "-", "")) expression is the filter you're seeing.
Remove that argument, you'll remove the filter.
app.DoCmd.OpenForm "Issue Details"
Side note, don't skip optional positional arguments like that (, , ,) - consider using named arguments instead, it makes it much clearer what arguments go to what parameters:
Now you need to move the recordsets cursor to your wanted position (can be provided by.OpenArgs):
app.DoCmd.OpenForm "Issue Details", _
OpenArgs:="[ID]=" & Abs(Replace(Right(search, 4), "-", ""))
'below could be in the form itself, e-g- Form_Load, (then ref by Me)
With Forms("Issue Details").RecordsetClone
.FindFirst Forms("Issue Details").OpenArgs
If .NoMatch then
' reaction on id not found
Else
Forms("Issue Details").Bookmark = .Bookmark
End If
End With

Related

Excel VBA: Input box with control characters

I'm using an input box to retreieve QR-codes from reader.
Unfortunately, the parameters in the QR-code are separated by group separator characters (decimal ASCII code 29) and these characters are being omitted.
The read in string contains all the data, but I can't distinguish the single parameters anymore.
What can I do? Is there another way to read in a string WITH all the control characters?
Thank you for your help!
Without further action your inputbox result indeed gets displayed as string without (visible) Chr(29) group separators ... even though the InputBox string result still contains those characters.
Therefore you need to convert the input eventually; the following Example demonstrates possible ways:
Sub testInput()
'a) Provide for QR results
Dim qr(0 To 2) As Variant
'b) Provide for default using Chr(29) group delimiters
Dim DefaultInput
DefaultInput = "a" & Chr(29) & "b" & Chr(29) & "c" & vbNewLine
'c) Execute InputBox (and assign to first QR result)
qr(0) = "0. Visible Input: " & InputBox("Enter QR", "QR input", DefaultInput)
'd) Convert visible inputs to 2nd and 3rd QR result
qr(1) = "1. Replaced Chr(29): " & Replace(qr(0), Chr(29), ",")
qr(2) = "2. Splitted Chr(29): " & Join(Split(qr(0), Chr(29)), "|")
'e) Show all three QR results
MsgBox Join(qr, vbNewLine)
End Sub
Further hint
If you need to get the different group results separately, I'd choose the split function (without joining the 0-based 1-dimensional array elements immediately, which was only done for display in the messagebox).

Validation of a dialog box for the update of fields "Mailmerge Fillin"

I'm looking for a way to validate those dialog boxes that pop up while updating a word document via excel vba.
The type of fields that I use is MailMerge Fields type "Fillin"
WordObj.ActiveDocument.MailMerge.Fields.AddFillIn
I'd like to write in them if possible too.
Update operation
Dialog box
It is by no means clear what you're trying to achieve. When you use:
ActiveDocument.MailMerge.Fields.AddFillIn
the resulting field doesn't show up in the document until something is done to cause it to update (e.g. performing the mailmerge). If you want the field to show up, use something like:
Dim wdFld As Object
With WordObj.ActiveDocument
Set wdFld = .Fields.Add(.Range.Characters.Last, -1, "QUOTE ""Default Text""", False)
wdFld.Code.Text = "FILLIN ""Some prompt"" \d ""Default Text"" \o"
End With
Other than that, you really do need to both explain how and why you're using a FILLIN field and post the code that updates it when the mailmerge is executed. After all, the use of a FILLIN field typically means the user is supposed to both make an input and press the OK/Cancel button.
To allow the specification of different ranges, prompts and defaults, you might use something like:
Sub FILLIN(StrBkMk As String, StrPrmpt As String, StrDflt As String)
Dim wdFld As Object
Dim quote As String
quote = char(34)
With WordObj.ActiveDocument
Set wdFld = .Fields.Add(.Bookmarks(StrBkMk).Range, -1, "QUOTE " & quote & StrDflt & quote, False)
wdFld.Code.Text = "FILLIN " & StrPrmpt & " \d " & StrDflt & " \o \* MERGEFORMAT "
End With
End Sub
where 'StrBkMk' is the name of a bookmark you want to position the field at. You'd then call the above code with something like:
Call FILLIN("FILLIN1", nom_signet, nouveau_texte_signet)
Or, if you're passing multi-word strings:
Call FILLIN("FILLIN1", "" & nom_signet & "", "" & nouveau_texte_signet & "")

Passing string result to query then export as csv

Good Afternoon,
I have an access query that contains a list of all my customers lets call that CUS
I have another query that has a list of ORDERS
I would like to write some VBS that cycles through the customer list and exports a csv file containing all orders that belong to that customer.
The vba would then move on to the next customer on the list and perform the same action.
Any help would be great.
Snippet of code below
almost there cant get the WHERE condition working it keeps displaying a popup for me to populate however the same string is feeding the msgbox fine here is a snippet below tht is within the loop
strcustcode = rs!OCUSTCODE
ordercount = rs!orders
TIMEFILE = Format$(Time, "HHMM")
MsgBox ([strcustcode] & " has " & [ordercount] & " orders")
StrSQL = "Select * From [24-ND_Cus] where [24-ND_Cus].[OCUSTCODE] = strcustcode "
Set qd = db.CreateQueryDef("tmpExport", StrSQL)
DoCmd.TransferText acExportDelim, , "tmpExport", "c:file.csv" db.QueryDefs.Delete "tmpExport" –
Don't use [ ] around VBA variables. Don't use parens for the MsgBox when you just want to give user a message. The parens make it a function that requires a response by user to set a variable.
MsgBox strcustcode & " has " & ordercount & " orders"
Concatenate the variable into the SQL statement. If OCUSTCODE is a text type field, use apostrophe delimiters for the parameter.
StrSQL = "Select * From [24-ND_Cus] Where [OCUSTCODE] = '" & strcustcode & "'"
I don't advise code that routinely modifies design and changing a query SQL statement is changing design. If the only change is filter criteria and a dynamic parameterized query won't work, I suggest a 'temp' table - table is permanent, data is temporary. Delete and write records to the table and export the table.

Control the behaviour of #ClientType formula in Lotus

I ran into an issue with the #ClientType formula in Lotus Notes. This formula should show the client type. From the Lotus help:
Returns "Notes" if the client type is a Lotus Notes client Returns
"Web" if the client type is a Web browser
#ClientType is useful within database formulas, form formulas, buttons
in forms, and "hide-when" formulas. Do not use #ClientType in column
formulas. #ClientType always returns "None" when executed in a server
background agent.
However if I run this code in an agent or action hotspot in the client:
x = Evaluate("#ClientType")
MsgBox x(0)
The result is "Web".
And if I use the notesDocument.RenderToRTItem( notesRichTextItem ) or notesDocument.ConvertToMIME( conversionType, options ) function, the #ClientType formula is also evaluated to "Web"
This is relevant because some fields in the document form in the document library use this formula in the hide when options. When a document is rendered to rich text or to MIME, this field is not included.
Is there any way to control the behavior of this formula? My only other option is to change the hide when formula's, but I would rather leave the design of the database as is.
Even though it's working on a computed field, if your agent gets that document handle then you can get from the computed field. Whereas it will not work in column formula which is already mentioned in help document.
It seems that the solution is to convert the session's convertmime flag to true after your doc.converttomime call
Code below is run from a scheduled agent.
Test 1 returns 'Nothing'
Test 2 returns 'Web'
Test 3 returns 'Nothing'
Sub Initialize
Dim s As New NotesSession
Dim db As NotesDatabase
Dim doc As NotesDocument
Dim vntClientType As Variant
Set db=s.Currentdatabase
On Error GoTo ErrorHandling
vntClientType = Evaluate("#ClientType")
MessageBox " Test 1 before converttomime " & vntClientType(0)
Set doc=New NotesDocument(db)
Call doc.converttomime
vntClientType = Evaluate("#ClientType")
MessageBox " Test 2 after converttomime" & vntClientType(0)
s.convertmime=True
vntClientType = Evaluate("#ClientType")
MessageBox " Test 3 after s.convertmime= true" & vntClientType(0)
Exit Sub
ErrorHandling:
Error Err, Error & " - " & ", at line " & Erl & { in "} & GetThreadInfo( 1 ) & {"}
End Sub

Custom Mapping tool for txt or excel

I have an excel dokument (tab delimitted). Every time before i can insert the excel in my program, i need to map the clients column names to the ones in my app.
So before i begin developing a mapping tool - it would be better if such already existed. But, i don't know i didn't find it.
This tool would actually read an excel or txt file, allow me to name all the names of the new columns on the right and drag and drop (for example).
Maybe this tool has an xml or something where i can define my custom columns, and then it would show op on the right side.
I hope you know what i mean and that someone also had the need for this.
Thanks
info update
I wanted to mention a few things as an update to my question if it's not to late: I have about 50 headers/columns (example: First Name, Middle Name, Street1, Street2,..). So what i always need do every time a client gives me his excel file (contacts backup) is manually copy data for each of his column to the one on my side. And the problem is, every client has different column names, and also some of the columns of the client can go to multiple columns on my side.
So i think, if i can't find a solution, i would make a c++/qt app, which takes an excell and lets me to assign (dragdrop,etc..) every column of his side to on or more columns of my side.
I haven't done any vb programming, so if you can be a bit more detailed about how to aproach the solution i vb that would be great.
Firs part of answer: You can achieve it with a simple vbscript. Copy this code in a vbs extension text file and double click.
Dim oCN As Connection
Dim fs As Scripting.FileSystemObject
Set oCN = New Connection
Set fs = New Scripting.FileSystemObject
sCSVFileName = "C:\Temp\Test1.csv"
sSourceSql = "SELECT field1 as f1, field2 as f2, ... FROM " &
fs.GetFileName(sCSVFileName )
sDestinationTable = "yourAppTable"
With oCN
.Provider = "Microsoft.Jet.OLEDB.4.0"
.Properties("Extended Properties").Value =
"TEXT;HDR=YES;FMT=TabDelimited;MAXSCANROWS=0"
.Open fs.GetFile(sCSVFileName).ParentFolder
End With
sSql = "INSERT INTO [ODBC;DRIVER={SQL Server};Server=" &
ServerName & ";Database=" & DBName & _
IIf(IntegratedSecurity, ";Trusted_Connection=Yes;", _
";UID=" & UID & ";PWD=" & PWD & ";") & _
"]." & sDestinationTable & " " & sSourceSql
oCN.Execute sSql, , adExecuteNoRecords
More info at microsoft social forums
Also, you can parametrize mapping (source and destination tables and mapping fields) with a external xml file.
Second part of answer: You ask if somebody else have this needed and if this is a good idea. Well, this is a very good proposal. And for this reason they are some solutions with this functionality.
First of all, this kind of technology is named ETL. Extract - Transform - Load.
Each database has its own tool
SQL Server Import and Export Wizard
Oracle data pump and loader
etc.
Also exists specific technologies:
SSIS from microsoft.
IBM WebSphere DataStage
etc.
All this tools have mapping columns capabilities.
i use a generic mapping mechanism for that, configured by a couple arrays where you put the names used in your app (aDsNames) with these in your source, the csv file in your case (aDbNames)
I walk the fields in the source, check if the getDbName(name) is in aDsNames and if so write the value in the insertstring to the database.
You can do this both ways, usually my app requests a field to the databasemodule on the server, this module translates to the databasename and does the select.
Hope this is helpfull..
Cheers
select case store
case "store1Midoc"
aDbNames = array("id" , "beheerder", "datumlijst", "rnr13" , "datvan", "dattot", "opmerking", "status" , "waarde", "kode" , "type")
aDsNames = array("id" , "persnr ", "datum ", "rnr13" , "datvan", "dattot", "opmerking", "status" , "waarde", "kode" , "type")
aTypes = array("number", "string", "date" , "string", "date" , "date" , "string" , "number", "number", "string", "string")
case .....
end select
Function getDbName(dsName)
Dim a
getDbName = "undefined"
If instr(join(aDsNames,","),dsName) Then
For a = 0 to UBound(aDbNames)
If aDsNames(a) = dsName Then
getDbName = aDbNames(a)
End If
Next
End If
End Function

Resources