Access 2007: Duplicating search form criteria to secondary query? - forms

I have an example search form query that I'd like to duplicate the output from in order to control an additional side query. I have two goals with this:
1) Send data to a report that matches the search results.
2) Be able to limit the columns that are being output to Excel - ie. exclude the search textboxes from the spreadsheet output (ie. hoping for detail section-only output).
To give a little bit more detail - this is going to be a read-only database and I'm trying to set this up to run in the background for the users so that they can have clean Excel exports and print exactly what they wish.
My code for the form search query looks like this:
Dim strWhere As String
Dim lngLen As Long
Const conJetDate = "\#mm\/dd\/yyyy\#"
If Not IsNull(Me.txtQ_ID) Then
strWhere = strWhere & "([Q_ID] = " & Me.txtQ_ID & ") AND "
End If
If Not IsNull(Me.txtAnswer) Then
strWhere = strWhere & "([Answer] Like """ & Me.txtAnswer & """) AND "
End If
If Not IsNull(Me.txtItem) Then
strWhere = strWhere & "([Item_Condition] Like """ & Me.txtItem & """) AND "
End If
If Not IsNull(Me.txtComments) Then
strWhere = strWhere & "([Comments] Like """ & Me.txtComments & """) AND "
End If
lngLen = Len(strWhere) - 5
If lngLen <= 0 Then
MsgBox "Please enter search criteria.", vbInformation, "Nothing to do."
Else
strWhere = Left$(strWhere, lngLen)
Me.Filter = strWhere
Me.FilterOn = True
End If
Is there a clean way to get this to feed back into SQL? I've seen this possibility suggested in another thread but there wasn't enough detail to go on.
Thank you in advance!
Matt B

Related

send each user their own individual emailed PDF report in Access

I've looked up the following code from another question on this site and have tried to apply it to my own, to no avail - I am trying to email out a pdf of my report to each user with only their specific information contained therein. If there are 15 users, then there will be 15 different emails sent out containing only their info. any help is very much appreciated.
Option Compare Database
Sub Mac1()
Dim rsAccountNumber As DAO.Recordset
Set rsAccountNumber = CurrentDb.OpenRecordset( _
"SELECT DISTINCT AccountNumber FROM UnAffirmed_Report_for_En Query")
With rsAccountNumber
Do Until .EOF
DoCmd.OpenReport "Unaffirmed Report", _
acViewPreview, _
WhereCondition:="AccountNumber = " & !AccountNumber, _
WindowMode:=acHidden
DoCmd.OutputTo acOutputReport, _
"Unaffirmed Report", _
acFormatPDF, _
"C:\users\rv\folder_name" & !AccountNumber & ".pdf"
DoCmd.Close acReport, "Unaffirmed Report", acSaveNo
.MoveNext
Loop
.Close
End With
End Sub
when I do though, I receive Run-time error '3075':
Syntax error (missing operator) in query expression 'AccountNumber = 1RV80014'
the account # is valid, but not sure why I am getting stuck here or how to fix it - super newbe to this.
Your account number is a String 1RV80014 and your Where condition:="AccountNumber = " & !AccountNumber states an Integer. So change it to a String Where condition:= "AccountNumber = '" & !AccountNumber & "'"

DoCmd.BrowseTo acBrowseToForm MULTIPLE WHERE conditions

I am new to Access 2010 VBA but have solid SQL background. I am trying to open/browse a form from a toogle button based on complex filter.
The form is called: FormSuivi
In SQL, the filter would be like this:
WHERE Randomise = 'Y' AND ActualSxDate is not null
AND datediff('d', Date(),ActualSxDate) > 140 AND DCD = 0;
In this Accessdatabase, the following field's types are:
Randomise: text
ActualSxDate: Date
DCD: Yes/no -> integer (-1/0)
For now, all I managed to do is to implement one condition at a time:
Private Sub Toggle25_Click()
DoCmd.BrowseTo acBrowseToForm, "FormSuivi", , "Randomise = """ & "Y" & """"
End Sub
How can all the conditions listed in SQL be squeezed into a VBA command line?
The parameter WhereCondition can be a full WHERE string, without the WHERE keyword. Including ANDs, parentheses, etc.
Single quotes ' help to keep the string readable (as opposed to """ constructs).
Variables need to be concatenated, e.g.
Dim S As String
S = "Randomise = '" & strRandomise & "' AND ActualSxDate is not null " & _
"AND datediff('d', Date(),ActualSxDate) > 140 AND DCD = " & bDCD
DoCmd.BrowseTo acBrowseToForm, "FormSuivi", , S

MS-Access between filter on form

Hi there I've created a form on access which looks like this:
I can make it so, that all the filters work, except for the Year and Length filters.
The Year boxes are unbound, and the left is called Year1 and the right one is Year2. I've tried to use Me.Filter code, but it doesn't work. It doesn't come up with an error, it just won't filter my data. So what I need is to make it so that the user can enter a year in Year1 and in Year2, and it filters the data between those two years. So for example they put 2000 in Year1 and 2010 in Year2, and then when they run the query it only shows data from 2000 to 2010.
This is the code I'm currently using:
Private Sub Year2_AfterUpdate()
Me.Filter = "[Year] BETWEEN #" & Me.Year1 & "# AND #" & Me.Year2 & "#"
Me.Filteron = true
Any help would be much appreciated! :)
(If you could explain what code does what that would be much appreciated too, so that I can learn to write it myself, and so that I can understand better! Thanks!)
You only use the "#" characters when you are using a date literal in your filter. If it is just a numeric you would use:
Me.Filter = "[Year] BETWEEN " & Me.Year1 & " AND " & Me.Year2
If [Year] actually IS a date then you should use:
Me.Filter = "[Year] BETWEEN #01/01/" & Me.Year1 & "# AND #12/31/" & Me.Year2 & "#"
Which will evaluate to [Year] BETWEEN #01/01/2010# AND #12/31/2011# if you enter 2010 and 2011 in the year textboxes.
You must use the name of the query (frmAufträgeQuery) and NOT the Form (frmAufträge):
On Error Resume Next
FromDate = "01.01.2021"
ToDate = "01.04.2021"
Me.Filter = "([frmAufträgeQuery].[Administrativ abgeschlossen] Between #" & Format(FromDate, "yyyy-mm-dd") & "# AND #" & Format(ToDate, "yyyy-mm-dd") & "#)"
Me.FilterOn = True

How to access a table within a range nested in another table?

In order to access the single table within a range (say, rngOuter) I used:
tblOuter = rngOuter.Tables[1];
After I placed a nested table within a range (say, rngInner) within that outer range's table, I found that:
tblInner = rngInner.Tables[1];
did not work. rngInner.Tables[1] references tblOuter, rather than the table within itself.
In fact, Tables collection of rngInner has only one element, and that is tblOuter. In order to access tblInner, I have to get at tblOuter.Range.Tables[1].
Does anyone know if I am making a mistake, or that's the way it is?
AFAIK "that's the way it is", but you can look for cells that contain tables by using Cell.Tables rather than Cell.Range.Tables. e.g. to look for cells in the current selection that contain tables you could use
Sub listInnerTables()
Dim c As Cell
Dim r As Range
Dim t As Table
Dim tcount As Long
Set r = Selection.Range
If r.Tables.Count > 0 Then
tcount = 0
For Each t In r.Tables
tcount = tcount + 1
For Each c In t.Range.Cells
If c.Range.InRange(r) Then
If c.Tables.Count > 0 Then
Debug.Print "Table: " & CStr(tcount) & _
vbTab & " Row: " & CStr(c.RowIndex) & _
vbTab & " Col: " & CStr(c.ColumnIndex) & _
vbTab & " Table count: " & CStr(c.Tables.Count)
End If
End If
Next
Next
End If
Set r = Nothing
End Sub

Displaying a recordset on a form in Access 2010 using VBA

I'm developing a data retrieval application in Access 2010 in which the user chooses which table, columns, and rows to view by selecting listbox entries. The VBA code generates a SQL statement from these choices and then creates an ADBDB.Recordset object from this.
How can I display the recordset records in Access? None of the grid controls work in Access 2010 and the subform just isn't designed for this purpose. Can someone recommend another strategy?
You could save the SELECT statement as a named query, then open the query as a datasheet. It's not really a form, but somewhat form-like.
Call DatasheetFromSql(strSql)
Public Sub DatasheetFromSql(ByVal pSql As String)
Const cstrQuery As String = "qryDiscardMe"
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim strMsg As String
On Error GoTo ErrorHandler
Set db = CurrentDb
db.QueryDefs.Delete cstrQuery
Set qdf = db.CreateQueryDef(cstrQuery, pSql)
DoCmd.OpenQuery cstrQuery, , acReadOnly
ExitHere:
On Error GoTo 0
Set qdf = Nothing
Set db = Nothing
Exit Sub
ErrorHandler:
Select Case Err.Number
Case 3265 ' Item not found in this collection. '
Resume Next
Case Else
strMsg = "Error " & Err.Number & " (" & Err.description _
& ") in procedure DatasheetFromSql"
MsgBox strMsg
GoTo ExitHere
End Select
End Sub
I opened the query read-only. If you want to allow users to edit the data returned by their custom queries, I would not recommend this approach. Instead I would invest the effort in the approach HK1 offered because it can support better control of the user data changes.
With the query opened as a datasheet, you can use Screen.ActiveDatasheet to inspect its properties. At least some of the methods are also available to you. For example you could resize/reposition the datasheet like this:
Screen.ActiveDatasheet.Move Left:=0, Top:=0, Width:=(4 * 1440), Height:=(3 * 1440)
The units are twips (1440 twips / inch), so that would make the width 4 in., height 3 in., and move it to the upper left corner of the Access window.
Here's what I think you'll have to do to get this kind of functionality.
You'll first need to create enough of the correct controls on a form to handle every possible scenario. You'll then need to set the form to be a datasheet form so that it appears as a grid.
Now set the controlsource on your controls to correspond with one of the fields in the recordset. On every control that is not in use needs to have it's ColumnHidden property set to true. You'll also have to change the caption of the associated label to show the appropriate column name for each control that will be visible.
Now, bind that form to your ADO recordset object.
Me.Recordset = rst
'or
Me.Subform1.Form.Recordset = rst
Is this a perfect solution? Most certainly not. Access doesn't have anything that compares to the DataGridView in .Net or even to the Grid controls that are used in VB6. In my opinion, you're really pushing the limits of Access to try to get this sort of functionality. It's like swimming upstream. You'll find that everything you do is going to be fairly difficult and some things just aren't going to be possible.
for an ADP Project where you can't have local MS Access query definitions, you can create a datasheet form with multiple textboxs named txt1, txt2,.... txt30 and labels name lbl1 ... lb30 and this code will set the form.recordsource and set the textbox.controlsource and the label.caption to the appropriate fields from an ADO recordset object. This form will allow you to view your ADO Recordset similar to the Docmd.OpenQuery method.
You must pass the ADO recordset's SQL statement to the form using the OpenArgs property of the form. the code below shows the VBA code to call\open the form (which shows the ADO Recordset like a query) and pass your sql string. The vba code on the form's load event will set all the control properties, resize the columns that have data and hide the columns that do not have a corresponding field from the ado recordset:
'stevekirchner 09/29/2012 Replace Access parameterized query with SQL Server in-line function
'DoCmd.OpenQuery "qry_SearchMaster_CaseTitles", , acReadOnly
strsql = "Select * from dbo.UDF__qry_SearchMaster_CaseTitles ('%" & Me.tbxSearchTerm.Value & "%') "
Call Display_ADO_Recordset_from_Datasheet_Form(strsql, "frm_Display_ADO_Recordset_Result1")
'create a non-form module and put the code for the sub Display_ADO_Recordset_from_Datasheet_Form
'and function fIsLoaded in it (this will allow you make several forms to view ADO recordset and
'call the code from one place\module):
Sub Display_ADO_Recordset_from_Datasheet_Form(sSQL As String, sFormName As String)
On Error GoTo Error_Handler
If fIsLoaded(sFormName) Then
DoCmd.Close acForm, sFormName
End If
DoCmd.OpenForm sFormName, acFormDS, , , acFormReadOnly, , OpenArgs:=sSQL
Exit_Sub:
Exit Sub
Error_Handler:
MsgBox Err.Description & " Error No: " & CStr(Err.Number)
Resume Exit_Sub
End Sub
Function fIsLoaded(ByVal strFormname As String) As Boolean
On Error GoTo Error_Handler
'Returns False if form is not open or True if Open
If SysCmd(acSysCmdGetObjectState, acForm, strFormname) <> 0 Then
If Forms(strFormname).CurrentView <> 0 Then
fIsLoaded = True
End If
End If
Exit_Function:
Exit Function
Error_Handler:
MsgBox Err.Description & " Error No: " & CStr(Err.Number)
fIsLoaded = False
Resume Exit_Function
End Function
'Create a datasheet view form (named frm_Display_ADO_Recordset_Result1) with 30 textboxes and 30
'30 labels named txt1 - txt30 and lbl1 - lbl30 and put this code in the form's module:
Option Compare Database
Private Sub Form_Load()
On Error GoTo Error_Handler
Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim rsClone As ADODB.Recordset
Dim strsql As String
Set conn = CurrentProject.Connection
Set rs = New ADODB.Recordset
strsql = Me.OpenArgs
rs.Open strsql, conn, adOpenStatic, adLockOptimistic
Set rsClone = rs.Clone
Call Update_Form_Controls("your text goes here", strsql, rsClone)
Exit_Sub:
rs.Close
conn.Close
Set rs = Nothing
Set conn = Nothing
Exit Sub
Error_Handler:
MsgBox Err.Description & "; Error Number : " & Err.Number, vbOKOnly
Resume Exit_Sub
End Sub
Sub Update_Form_Controls(Header_Label As String, SQL As String, CloneRS As Recordset)
Dim rsCount As Integer
Dim i As Integer
On Error GoTo Error_Handler
Me.Form.Caption = Replace(SQL, "Select * From ", "Display: ")
rsCount = CloneRS.RecordCount
If rsCount <= 0 Then
MsgBox "The Query did not return any data to view", vbOKOnly
DoCmd.Close
Else
Me.Form.SetFocus
Me.RecordSource = SQL
i = 1
Do Until i = 31
Me("lbl" & i).Caption = ""
Me("txt" & i).ControlSource = ""
Me("txt" & i).ColumnHidden = True
i = i + 1
Loop
i = 1
With CloneRS
For Each Field In .Fields
On Error Resume Next
Me("lbl" & i).Caption = .Fields(i - 1).Name
Me("txt" & i).ControlSource = .Fields(i - 1).Name
Me("lbl" & i).Visible = True
Me("txt" & i).ColumnHidden = False
Me("txt" & i).SizeToFit
i = i + 1
'Debug.Print Field.Name
On Error GoTo 0
Next Field
End With
End If
Exit_Sub:
Me.Requery
Exit Sub
Error_Handler:
MsgBox Err.Description & "; Error Number : " & Err.Number, vbOKOnly
Resume Exit_Sub
End Sub
I don't use ADO but simply VBA, in which case above approach is wrong: one doesn't need any means for displaying an existing recordset in a form, but should on the contrary define an adequate recordset within the form !
Instead of creating MyDataBase.OpenRecordset ("SELECT … [SQL query] ;"), just set the form's RecordSource to the very same query definition:
Forms![MyDisplayForm].RecordSource = "SELECT … [SQL query] ;"
Forms![MyDisplayForm].Requery
For me this works perfectly (Windows 7 pro ×64 / MS Office pro ×64)