I use Kofax Transform to extract data from OCR.
For this i have a form with several inputs. Basically : name, surname, email.
My issue concerns the validation step.
I want to update the input fields on specific event (click on enter when the email field is selected and update the values from a database). On this database table I have 4 fields : id, name, surname and email
It's my first VBA expertience and I have to create a script:
Private Sub FillFormOneEmailValidated(ByVal pXDoc As CASCADELib.CscXDocument)
'define required properties
Dim rs As ADODB.Recordset
Dim cn As ADODB.Connection
Dim sqlRequest As String
Dim email As String
Dim dbHostServer As String
Dim dbUsername As String
Dim dbPassword As String
Dim dbName As String
Dim dbConnString As String
'Prapare the db connection
Set rs = New ADODB.Recordset : Set cn = New ADODB.Connection
dbHostServer = "127.0.0.1"
dbUsername = "root"
dbPassword = "root"
dbName = "dbtest"
'build the connection string and open connection to database
dbConnString = "Provider=MSDASQL;Driver={MySQL ODBC 5.3 Unicode Driver};
dbConnString = dbConnString & "Server=" & dbHostServer & ";"
dbConnString = dbConnString & "UID=" & dbUsername & ";"
dbConnString = dbConnString & "PWD=" & dbPassword & ";"
dbConnString = dbConnString & "database=" & dbName
'Create recordset and set conncetion
Set rs = New ADODB.Recordset : : Set cn = New ADODB.Connection
cn.ConnectionString = dbConnString
cn.Open
'build query
sqlRequest = "SELECT name, surname, email FROM users WHERE email = " & email
Set rs = cn.Execute(sqlRequest)
'iterate the values of the sql request
On Error Resume Next
rs.MoveFirst
pXDoc.Fields.ItemByName("name") = CStr(sqlRequest("name"))
rs.Close : Set rs = Nothing
cn.Close : Set cn = Nothing
End Sub
Here are my issues :
it seems that this code is not correct.
How can i "observe" an event on the email input (form) in KTA Transform ?
Avoid building sql query like that since its a potential injection risk. Look into using parameters. (Or hope nobody's kid is named bobby drop table, or be subject to a malicious user)
Also passwords in scripts are not recommended.
I'd look into the already built in functionalities of The database locator. And database dialog you can add to your validation mask.
If script is the only possible thing
You can use multiple events to to this. One way as you said is when the field is confirmed ValidationForm_AfterTableCellChanged.
You can see events available to you in the Project builder/Script editor by the dropdown options
enter image description here
Not sure for KTA, but in normal KT you can debug and observe other how methods are doing by enabling the Script debugging in the synchronization options.
The error in the script looks obvious
sqlRequest is your query as String variable. You must get your row data from the recordset. (i have not checked the rest of the script)
Related
I'm struggling with ADO connections/recordsets.
My problem statement is: a function that will return the first value of a chosen field, in a chosen .csv file.
I am doing this to identify variably-named .csv files before adding the data to the relevant tables in a database. I am making the assumption that this field is always present and that either it is consistent throughout the file, or only relevant ones are grouped (this is controlled higher up the chain and is certain enough).
My code is being run as part of a module in an MS Access database:
Public Function GetFirstItem(File As Scripting.File, Field As String)
Dim Conn As ADODB.Connection, Recordset As ADODB.Recordset, SQL As String
Set Conn = New ADODB.Connection
Set Recordset = New ADODB.Recordset
'Microsoft.ACE.OLEDB.16.0 / Microsoft.Jet.OLEDB.4.0
Conn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.16.0;Data Source=""" & File.ParentFolder & _
"""; Extended Properties=""text;HDR=Yes;FMT=Delimited;"";"
SQL = "SELECT " & Field & " FROM """ & File.Name & """ LIMIT 1"
Debug.Print Conn.ConnectionString
Debug.Print SQL
Conn.Open
Recordset.Source = SQL
Recordset.ActiveConnection = Conn.ConnectionString
Recordset.Open
Recordset.MoveFirst
'GetFirstItem = Recordset!Questionnaire
Recordset.Close
Conn.Close
Set Recordset = Nothing
Set Conn = Nothing
End Function
ConnectionString = Provider=Microsoft.ACE.OLEDB.16.0;Data Source="D:\Documents\Jobs\TestPath"; Extended Properties="text;HDR=Yes;FMT=Delimited;";
Field = Questionnaire
SQL = SELECT Questionnaire FROM "test.csv" LIMIT 1
I get an error on Recordset.Open of:
This may be (is probably) down to a complete lack of understanding of how ADO connections/recordsets work. I have tried sans-quotes and it complains about a malformed FROM expression. Additionally, once this hurdle is overcome I am unsure of the syntax of how to return the result of my query. If there is a better way of doing this I am all ears!
Thanks.
In Access you don't need ADO library to query a CSV file:
Public Function GetFirstItem(File As Scripting.File, Field As String) As String
Dim RS As DAO.Recordset, SQL As String
SQL = "SELECT TOP 1 [" & Field & "]" _
& " FROM [" & File.Name & "]" _
& " IN '" & File.ParentFolder & "'[Text;FMT=CSVDelimited;HDR=Yes];"
Debug.Print SQL
Set RS = CurrentDb.OpenRecordset(SQL)
GetFirstItem = RS(0)
RS.Close
Set RS = Nothing
End Function
Usage:
?GetFirstItem(CreateObject("Scripting.FileSystemObject").getfile("c:\path\to\your\file.csv"), "your field")
I am trying to write a query in MS access to open a connection to a local SQL Server and then to import select tables into MS Access.
My code runs until the Cn.Execute statement. I get
Run-time error '-2471765 (80040e37)' [Microsoft][ODBC SQL Server Driver][SQL Server] Invalid Object Name 'dbo_SQLServertable'.
I need to import additional tables so I need a code that will work when I change table names.
Private Sub Command28_Click()
Dim Cn As ADODB.Connection
Dim Server_Name As String
im Database_Name As String
Dim User_ID As String
Dim Password As String
Dim SQLStr As String
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Server_Name = "" ' Enter your server name here
Database_Name = "Test" ' Enter your database name here
User_ID = "" ' enter your user ID here
Password = "" ' Enter your password here
Set Cn = New ADODB.Connection
Cn.Open "Driver={SQL Server};Server=" & Server_Name & ";Database=" & Database_Name & ";"
Cn.Execute "INSERT INTO Access Table SELECT dbo_SQLServerTable.* FROM dbo_SQLServerTable;"
Set rs = Nothing
Cn.Close
Set Cn = Nothing
I made changes and I get a new error message
Run-time error '-2147216900 (80040e14)' [Microsoft][ODBC SQL Server Driver][SQL Server] Cannot Insert the value NULL into column 'DiagnosisOrdinal', table 'Office.dbo.Test' column does not allow nulls. Insert fails.
It appears that my insert statement is still referencing (or trying to reference) a table in the SQL server. 'Office' is the database name that I am pulling from.
Do I have to close the connection and then paste the data into my local Access table? Will I then have to re-open and close the connection if I want to do this for multiple tables?
I changed my execute statement from
Cn.Execute "INSERT INTO Access Table SELECT dbo_SQLServerTable.* FROM dbo_SQLServerTable;"
to
Cn.Execute "INSERT INTO Test(VisitID, Provider) SELECT VisitID, Provider FROM dbo.SQLServerTable;"
Least amount of code I can think of is to use a pass-through query.
Setup a PT query to the server database in question.
Then your code to create a new table in access would look like:
Sub TestImport()
Dim strSQL As String
With CurrentDb.QueryDefs("qryPassR")
.SQL = "select * from tblHotels"
End With
Dim strLocalTable As String
strLocalTable = "zoo"
CurrentDb.Execute "select * into " & strLocalTable & " FROM qryPassR"
End Sub
The above of course assumes you setup the connection to sql server (one database) when you created the PT query. The above approach is nice since you don't mess around with connection strings in code.
However, given that you need (want) to specify the database (and likely server), then above becomes this:
Sub TestImport2()
Dim strSQL As String
Dim strServer As String
Dim strDatabase As String
Dim strUser As String
Dim strPass As String
strServer = ""
strDatabse = ""
strUser = ""
strPass = ""
Dim strLocalTable As String
Dim strServerTable As String
With CurrentDb.QueryDefs("qryPassR")
.Connect = dbCon(strServer, strDatabase, strUser, strPass)
.SQL = "select * from " & strServerAble
End With
CurrentDb.Execute "select * into " & strLocalTable & " FROM qryPassR"
End Sub
The above uses a "handy" function to create your connection string.
That function is as follows:
Public Function dbCon(ServerName As String, _
DataBaseName As String, _
Optional UserID As String = "", _
Optional USERpw As String, _
Optional APP As String = "Office 2010", _
Optional WSID As String = "Import") As String
' returns a SQL server conneciton string
dbCon = "ODBC;DRIVER=" & SQLDRIVER & ";" & _
"SERVER=" & ServerName & ";" & _
"DATABASE=" & DataBaseName & ";"
If UserID <> "" Then
dbCon = dbCon & "UID=" & UserID & ";" & "PWD=" & USERpw & ";"
End If
dbCon = dbCon & _
"APP=" & APP & ";" & _
"WSID=" & WSID & ";" & _
"Network=DBMSSOCN"
End Function
Edit
Poster has asked for solution to append data into a EXISTING table.
In that case, simply change this:
CurrentDb.Execute "select * into " & strLocalTable & " FROM qryPassR"
to
CurrentDb.Execute "INSERT INTO " & strLocalTable & " SELECT * FROM qryPassR"
You don't want the table prefix in your SELECT from the SQL table. Just do SELECT * FROM dbo_SQLServerTable; Best practice, though, is not to use SELECT * but rather specify the columns in case the table schemas ever change.
There's a few suggestions for this particular issue
Pass thru queries
Linked Tables from SQL Server. Youll prolly have to set up a dsn file which isnt too terribly difficult.
Or handle it directly in SQL Server Insert into Access from SQL Server
ODBC connection via VBA (what youre doing and seemingly the most convoluted)
All of these approaches will work fine. I suggest linked tables so you dont duplicate data but thats a cinsderation fro you since I dont knwo the requirements of the project.
dbo_SQLServerTable is an Access table name, not SQL server table name. Because you already created the linked table dbo_SQLServerTable, you can use the following VBA code.
Currentproject.connection.execute "INSERT INTO MyAccessTable(fld1, fld2, fld3) SELECT fld1, fld2,fld3 FROM dbo_SQLServerTable"
There is no need to create connection object in VBA code. Currentproject.connection is always available to be referenced.
I have an Access DataBase and a form in Excel VBA. All the data I input into the DB is input through the VBA form.
This DB contains all the benefits cards we already received this year in the company. But the same employee can ask for the card twice or more, so we'll have more than one record on the DB for him.
What I need is when the number of records is greater than one, the SQL statement result should appear in a Excel report.
I use the SELECT (*) COUNT statement to know when there is more than one record that is compatible with the search criterion. But I can't make the result appear in an Excel file.
Here is my code:
Public Function Relatorio()
Dim sql As String
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim rel As String
Set cn = New ADODB.Connection
cn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & enderecoDB & ";Jet OLEDB:Database"
cn.Open
Set rs = New ADODB.Recordset
sql = "INSERT INTO OPENROWSET('Microsoft.ACE.OLEDB.12.0', 'Excel 12.0;Database=" & enderecoDB & ";', 'SELECT * FROM [Planilha1$]') SELECT * FROM controle WHERE BP = " & controlectform.nmbpbox.Value & ";"
rs.Open sql, cn
End Function
When I run this code it gives me a message saying something like:
Can't locate the OPENROWSET Table exit
I'm not able to install new programs, so I need to do this using only Excel VBA and the Access DB.
How can I make this work?
I don't believe Access supports the OPENROWSET, dynamic table you're working with there. I have a lot of old projects that do this though, so here's my method
Public Function Relatorio()
Dim sql As String
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim rel As String
Set cn = New ADODB.Connection
cn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & enderecoDB & ";Jet OLEDB:Database"
cn.Open
Set rs = New ADODB.Recordset
dim path_To_XLSX
dim name_of_sheet
path_To_XLSX = "c:\temp\output.xlsx"
name_of_sheet = "Planilha1"
sql = sql = "SELECT * INTO [Excel 12.0;Database=" & path_To_XLSX & "]." & name_of_sheet & " FROM controle WHERE BP = '" & controlectform.nmbpbox.Value & "';"
rs.Open sql, cn
'If this application is in an unsecure environment, use the following code instead! This is to prevent a SQL injection, security concern here.
'As it is an Access Database, this is likely overkill for this project
'Create Command Object.
Set Cmd1 = New ADODB.Command
Cmd1.ActiveConnection = cn
cmd1.CommandText = "SELECT * FROM controle INTO [Excel 12.0;Database=" & path_To_XLSX & "]." & name_of_sheet & " WHERE BP = ?"
' Create Parameter Object.
Set Param1 = Cmd1.CreateParameter(, adInteger, adParamInput, 5) 'use adVarchar for strings(versus adInteger), https://www.w3schools.com/asp/met_comm_createparameter.asp
Param1.Value = controlectform.nmbpbox.Value
Cmd1.Parameters.Append Param1
Set Param1 = Nothing
Set Rs = Cmd1.Execute()
End Function
I had this challenge so many years ago that I cant remember but this link ring the bell. check if it help.
https://stackoverflow.com/a/28889774/382588
try { connw.Open(); OleDbCommand command; command = new OleDbCommand( "Update Deliveries " + "SET Deliveries.EmployeeID = ?, Deliveries.FIN = ?, Deliveries.TodaysOrders = ? , connw); command.Parameters.Add(new OleDbParameter("#EMPID", Convert.ToDecimal(empsplitIt[1]))); command.Parameters.Add(new OleDbParameter("#FIN", truckSplit[1].ToString())); command.Parameters.Add(new OleDbParameter("#TodaysOrder", "R")); catchReturnedRows = command.ExecuteNonQuery();//Commit connw.Close(); } catch (OleDbException exception) { MessageBox.Show(exception.Message, "OleDb Exception"); }
you can use this, to print the actual SQL.
Private Sub Command2_Click()
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 Sub
Public Sub TextOut(OutputString As String)
Dim fh As Long
fh = FreeFile
Open "C:\Users\rs17746\Desktop\Text_Files\sample.txt" For Append As fh
Print #fh, OutputString
Close fh
End Sub
Here is one more version for you. This will export the results of each query, each to a separate text file.
Private Sub Command0_Click()
Dim qdf As QueryDef
Dim strFileName As String
For Each qdf In CurrentDb.QueryDefs
If Left(qdf.Name, 1) <> "~" Then
'you need to figure out TransferText command. Maybe
'you won't be lazy and expect people to read it to
'you and tutor you on how it works.
strFileName = qdf.Name
'Docmd.TransferText ....
DoCmd.TransferText transferType:=acExportDelim, TableName:=strFileName, FileName:="C:\test\" & strFileName & ".txt", hasfieldnames:=True
End If
Next qdf
MsgBox "Done"
End Sub
I have an Excel file that exports data into Word. It includes a cover page and grabs the user name ("First.Last") and changes it to "First Last" but I also need to include the user's professional title. This information is housed in an Access table. It has a field called Name and a field called Title. The Name field match exactly to User with no duplicates.
I have tried about eight different methods I've found online to grab this value from the table. The table will never happen to be open so I can't use "CurrentDB()".
I just need to be able to reach into the table in a database, grab the "title" value given that the value of the field "Name" is equal to the value of User (user name from the environment - the person using the excel file).
If it helps, I can provide examples of the different chunks of code I've used so far.
User is the username from the environment
tblPickName is the table I am trying to open
Path is the directory and file where the table is located
tblPickName has 2 fields, Name and Title
I need to grab the Title from this table and set it to my variable "Title" as long as Name equals User. Then I can export the username and title to Word along with the rest of the data.
Dim Path As String
Dim User As String
Dim Title As String
Dim db As DAO.Database
Dim rs As DAO.Recordset
User = Environ("UserName")
User = Replace(User, ".", " ")
User = StrConv(User, vbProperCase)
Path = "Directory\Name.mdb"
Set db = DBEngine.OpenDatabase(Path)
Set rs = db.OpenRecordset("SELECT tblPickAnalyst.Title FROM tblPickAnalyst WHERE [Analyst]='" & User & "'")
Title = rs!Title
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
docWord.Bookmarks("AnalystName").Range.Text = User
docWord.Bookmarks("AnalystTitle").Range.Text = Title
Try this:
Public Sub JohnTayloristheBest()
Dim conAccess As ADODB.Connection
Set conAccess = New ADODB.Connection
Dim rdsAccess As ADODB.Recordset
Dim strTitle as String
With conAccess
.ConnectionString = "Data Source= **insert filepath here** "
.Provider = "Microsoft.ACE.OLEDB.12.0"
.Open
End With
With rdsAccess
.Open "SELECT tblPickName.Title FROM tblPickName WHERE tblPickName.Name = '" & Environ("username") & "';", conAccess
If Not .EOF And Not IsNull(.fields(0)) Then
strTitle = .fields(0)
Else
Msgbox "Error: No record in the database for " & Environ("username")
End If
.Close
End With
conAccess.Close: conAccess = Nothing
End Sub
Be sure to select the correct references by doing this: http://msdn.microsoft.com/en-us/library/windows/desktop/ms677497(v=vs.85).aspx
Also, this is my first answer ever written on this site (or any other for that matter), so be kind.
Try this:
Public Function getTitle(name As String)
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = DBEngine.OpenDatabase("E:\Temp\Database.mdb")
Set rs = db.OpenRecordset("SELECT Title FROM tblPickName WHERE Name='" & name & "'")
If rs.RecordCount > 0 Then
getTitle = rs!Title
End If
rs.Close
db.Close
End Function
Ensure read access on table tblPickName (for Administrator)
Here is the final solution. Thank you to everyone who helped!
Dim Path As String
Dim User As String
Dim Title As String
Dim db As DAO.Database
Dim rs As DAO.Recordset
User = Environ("UserName")
User = Replace(User, ".", " ")
User = StrConv(User, vbProperCase)
Path = "Directory\FileName"
Set db = DBEngine.OpenDatabase(Path)
Set rs = db.OpenRecordset("SELECT tblPickAnalyst.Title FROM tblPickAnalyst WHERE [Analyst]='" & User & "'")
Title = rs!Title
rs.Close
db.Close
Set rs = Nothing
Set db = Nothing
docWord.Bookmarks("AnalystName").Range.Text = User
docWord.Bookmarks("AnalystTitle").Range.Text = Title
I've used php for everything, but now I need to look up something in MS SQL with ASP.
I cannot for the love of God figure out how to bind post parameters to a prepared statement and print the results.
I need to fetch only 1 row for each lookup, where the SQL statement would look like:
SELECT ID,NAME FROM MEMBERS WHERE ID = ?
I've gotten as far as this, from an example and reading a bit of posts:
Response.Buffer = True
On Error Resume Next
Dim host
Dim port
Dim user
Dim password
Dim database
host = "host"
port = "1433"
user = "user"
password = "pass"
database = "database"
Dim conn
Set conn = Server.CreateObject("ADODB.Connection")
Dim ds
ds = host & "," & port
Dim connString
connString = "Provider=SQLOLEDB;Data Source=" & ds & ";Network Library=DBMSSOCN;Initial Catalog=" & database & ";User Id=" & user & ";Password=" & password & ";"
conn.Open connString
Dim cmdPrep1 As New ADODB.Command
Set cmdPrep1.ActiveConnection = cn
cmdPrep1.CommandText = "SELECT ID,NAME FROM MEMBERS WHERE ID =?"
cmdPrep1.CommandType = adCmdText
cmdPrep1.Prepared = True
This is where my knowledge ends.
How would I bind input paramters (POST) to the above and do a print of the fetched row?
Why are basic ASP examples so hard to come by vs. php? Seems odd to me.
this will not work in classic asp:
Dim cmdPrep1 As New ADODB.Command
you have to use server.createobject like so:
dim cmdPrep1 : set cmdPrep1 = server.createobject("ADODB.Command")
cmdPrep1.ActiveConnection = cn
cmdPrep1.CommandType = adCmdText
cmdPrep1.CommandText = "SELECT ID,NAME FROM MEMBERS WHERE ID =?"
cmdPrep1.parameters.Append cmd.createParameter( "ID", adInteger, , , Request.Form("nameOfIDField") )
dim rs : set rs = cmdPrep1.execute
now you have an ADODB.Recordset in your variable rs.