Query Disconnected RecordSet - vbscript

Background: a LOB app we use has the ability to use macros written in VBScript, but no access to WScript, etc., as far as I know.
I have successfully received user input, passed it to a stored procedure on a SQL Server, and returned a recordset to the VBScript macro in the application.
What I want to do now, is write a function or loop or something, that for as long as there is a record left in the recordset, accept additional user input, and check this against the returned recordset.
The recordset returned from SQL Server contains two columns: PART_ID and PART_QTY. For as many number of entries there are, I want to accept additional user input, lets say PART_ID_INPUT and PART_QTY_INPUT, and validate it against the in-memory recordset.
My biggest problem is working with the disconnected recordset.

When in doubt, read the documentation. You can use the Filter and RecordCount properties to determine if the recordset contains matching records:
part_id_input = InputBox("Enter part ID:")
If part_id_input <> "" Then
rs.Filter = "PART_ID = '" & part_id_input & "'"
If rs.RecordCount > 0 Then WScript.Echo "Found matching record."
End If
The filter is cleared by setting it to an empty string:
rs.Filter = ""
The current record can be removed from the recordset using the Delete method:
rs.Delete
Navigate through records via MoveFirst/MoveLast/MoveNext/MovePrevious.

Related

How to use a variable for the criteria in a query to restrict the query to the active form?

I have form named "frmBond-MuniDetailsAE". It has a combo box named "cboStep". The Row Source for cboSteps is an embedded query that retrieves records from a table named "tblBond-Steps", and it has as Criteria -
[Forms]![frmBond-MuniDetailsAE]![SYM]. This restricts the query to records in tblBond-Steps to only those that have a SYM field that matches that field in the form. This works fine. But I would like to be able to copy and reuse the form for other types of bonds, and I don't want to have to rewrite the embedded query in each copied form. So I wanted to use a variable in the query criteria that would reference the current form.
Following answers given in StackOverflow at How do I reference the current form in an expression in Microsoft Access?, I wrote a Public Function named "FormName()". Here is the function:
Public Function FormName() As String
Dim frmCurrentForm As Form
Set frmCurrentForm = Screen.ActiveForm
FormName = "[Form]![" & frmCurrentForm.Name & "]" & "![SYM]"
End Function
Then in the embedded query for the combo box, I entered "FormName()" as the criteria. Here is the SQL for that query:
SELECT [tblBond-Steps].SYM, [StepDate] & " # " & [Cpn] AS Steps, Format([tblBond-Steps].
[StepCpn],"0.0000%") AS Cpn, [tblBond-Steps].StepDate
FROM [tblBond-Steps]
WHERE ((([tblBond-Steps].SYM)=FormName()))
ORDER BY [tblBond-Steps].StepDate;
But when I open the form with the above query as the Row Source for cboSteps, I get VBA Run-time error '2475': "You entered an expression that requires a form to be the active window."
I can't figure out what I'm doing wrong. Can someone help me?
You must return the value, not the expression:
Public Function FormName() As String
Dim frmCurrentForm As Form
Set frmCurrentForm = Screen.ActiveForm
FormName = frmCurrentForm![SYM].Value
End Function

add variable field value to output file name

I have a db that imports files in to temp tables prior to exporting the data to excel and appending the temp data to the main table. Each of the files loaded to the temp tables had a column with the same unique value for each record. I would like to create a query to used to filter on the first and add that value from the query to my file naming convention for the person that has to work the output files.
I've created the query that filters on the first but I am not able to find a way to incorporate that result into the file naming for the output.
Function Export_2nd_Level_Excel()
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, "2ndLevel", "\pbfsvr01\pbf\PharmNetwork\Audits_Pharmacy\Provider_Audits\Completed Audit files\2nd_Level\" & "[Insert NPI]" & Format(Now, "_ddmmmyy""_2ndLevel_to_PharmAudit") & ".xlsx", True
End Function
I would like to have the "[Insert NPI]" be the actual value from the query that pulls the first of NPI.
after playing around with this for quite some time, I was able to make this work
Function Export_2nd_Level_Excel()
Set db = CurrentDb
Set recd = db.OpenRecordset("2nd_level_NPI")
Dim NPI As String
recd.MoveFirst
NPI = recd![NPI]
DoCmd.TransferSpreadsheet acExport, acSpreadsheetTypeExcel12Xml, "2ndLevel", "\pbfsvr01\pbf\PharmNetwork\Audits_Pharmacy\Provider_Audits\Completed Audit files\2nd_Level\" & NPI & Format(Now, "_ddmmmyy""_2ndLevel_to_PharmAudit") & ".xlsx", True
End Function

VBA function to get windows user name [duplicate]

I would like to know if there is a way to get system username and use it directly in an MS Access query. I have made a parameter work within a query from a combo box on a form and I have also acquired system name in Access VBA using ENVIRON ("USERNAME").
Kindly let me know if this is possible.
You need to create a VBA function that returns the username, and then use the function in the query.
Public Function GetUserName() As String
' GetUserName = Environ("USERNAME")
' Better method, see comment by HansUp
GetUserName = CreateObject("WScript.Network").UserName
End Function
and
SELECT foo FROM bar WHERE myUserName = GetUserName();
My solution kept all the work in VB.
I used a variable for the windows login username and then created a SQL string with that variable inserted. Lastly, I updated the query behind the form to use this new SQL string.
The CHR(34) puts quotes around the name as it is now a string inside the SQLSTR and needs to be within a set of quotes.
If you have a complex SQL statement, write it in the QBE using a string for the name and all the other variables, then switch to the SQL view and replace it using a VBA variable as shown below.
MyName = Environ("username")
sqlstr = "SELECT * From Projects WHERE ( ((Projects.LeadEngineer)=" & Chr(34) & MyName & Chr(34) & " AND ActiveYN = True ));"
Forms![Main Form].RecordSource = sqlstr
You can use SYSTEM_USER if the query is being executed in a SQL Server, that will retrieve the user name connected to the database (for that, make sure you are not using fixed user name in your connection string)
Yes - you can use the 'CurrentUser' function in your query. Here I've included it as a field and criteria.
SELECT Field1, Field2, [CurrentUser] AS UserName FROM Table1 WHERE Field1 = [CurrentUser];

Cannot get classic ASP parameterized queries working when using Symmetric key encryption

I have the key and certificate setup ok on the database and I can encrypt ok when entering queries directly using HeidiSQL. But the problem I am having is getting this to work using classic asp.
I have setup a simple table for testing which contains an auto increment identity column and a var binary max column for holding the encrypted data.
Here is my code:
chtest.commandtext="OPEN SYMMETRIC KEY SymmetricKey DECRYPTION BY CERTIFICATE [Certificate];"
set rschtest = chtest.execute
chtest.commandtext="INSERT into thetable(thevalue) values(?)"
chtest.Parameters.Append chtest.CreateParameter ("#thevalue", adVarBinary, adParamInput,8000, "EncryptByKey(Key_GUID('SymmetricKey'), 'some text here')" )
set rschtest = chtest.execute
This seems to work as binary data gets entered into the table but when decrypting it directly on the server then it just shows 'Null'.
Doing these queries directly on the server does work, for example:
OPEN SYMMETRIC KEY SymmetricKey DECRYPTION BY CERTIFICATE Certificate
INSERT INTO thetable (thevalue) VALUES (EncryptByKey(Key_GUID('SymmetricKey'), 'some text here'))
and then...
OPEN SYMMETRIC KEY SymmetricKey DECRYPTION BY CERTIFICATE [Certificate]
SELECT CONVERT(varchar, DecryptByKey(thevalue)) AS thevalue FROM thetable
works and shows the correct decrypted value.
I think the problem when using the classic asp method is something to do with having to insert the encrypted string into the varbinary as a varchar? Or something like this.
Also, if I don't use parameterized queries then everything works ok but obviously I want to use prepared queries for security.
Note this this is a legacy application so I have to use classic asp.
Any help appreciated.
You need a bit of restructuring of the ADODB.Command at the moment the .CreateParameter() call makes no sense. You should always pass the base data type of a value through parameters any manipulation afterwards (in this case by EncryptByKey()) should be done inside the query defined by CommandText.
Dim sql: sql = ""
sql = sql & "OPEN SYMMETRIC KEY SymmetricKey DECRYPTION BY CERTIFICATE [Certificate]" & vbCrLf
sql = sql & "INSERT INTO thetable (thevalue) VALUES (EncryptByKey(Key_GUID('SymmetricKey'), ?))"
With chtest
.ActiveConnection = your_connection_string
.CommandText = sql
.CommandType = adCmdText
Call .Parameters.Append(.CreateParameter("#thevalue", adVarChar, adParamInput, 8000, "some text here")
'As you are doing an INSERT use adExecuteNoRecords to cut down on processing
'and improve performance.
Set rschtest = chtest.Execute(, , adExecuteNoRecords)
End With
You will notice that I've changed
.CreateParameter ("#thevalue", adVarBinary, adParamInput,8000, "EncryptByKey(Key_GUID('SymmetricKey'), 'some text here')" )
to
.CreateParameter("#thevalue", adVarChar, adParamInput, 8000, "some text here")
This is because when you are manipulating a base value in this case the string 'some text here' any manipulation of it needs to be done outside of passing the base value.
That is why the .CommandText now contains EncryptByKey(Key_GUID('SymmetricKey'), ?) so only the base value is passed via the Parameter collection during execution.

Loop to run a series of queries to append a table for each record in a different table. MS Access 2010

Here is what I need to do:
I have a series of queries that I use to create a final report with multiple columns of statistics for an item. I have a table set up with a key for each item. What I need to do is create a loop that runs the series of queries for an item and uses the final query to append the results to "report" table.
I have all of the Make Table queries set up and the final Append query. There are two queries that require the key, the rest of the queries are dependant on the results of the first two. So, I need to use that key as a parameter in those two queries. What I need is a loop that will for each key in the "Items" table run the queries on that key, then loop.
I have a module setup to run the complete set of queries, but right now I need to run it for each item. My thinking is that I need a "for i in items..." type loop, but I do not know how to do that in VBA
Using MS Access 2010
As far as I understand you want to run multiple queries where queries are saved in a table. Some of the queries depends on parent query.
pseudo logic:
Run and Execute Parent Query
If result exists retrieve value
Start loop until parent query has values
Retrieve/construct sub queries
Execute sub query
End loop
some pseudo code:
dim MyDb as Dao.Database
dim myRs as Dao.Recordset
set mydb = currentdb
dim SQL_PARENT as string
sql_parent = "" ' Retrieve your parent query here
sql_parent = vba.replace(sql_parent, "searchkey", "replace_key") ' Replace keys
' or if you have the keys in a table then use the dlookup() function to replace keys
set myrs = mydb.openRecordSet(sql_parent)
'do error trapping here
dim iResult = nz(myrs("ResultField"),"")
'follow the parent query operation
'construct the sub queries
dim RS_SUB as DAo.Recordset
dim SQL_SUB as string
dim I as integer
for i = 1 to total of your query collection
sql_sub = query_collection(i)
sql_sub = vba.replace(sql_sub,"searchkey",iResult)
set rs_sub = mydb.openrecordset(sql_sub)
next i
note: this is just a pseudo answer to help you to understand the possibilities to your scenario.

Resources