Print Dialog in MS-Access - vba

I want to open a print dialog box. I haven't programmed in VB for a decade and I am more than a little rusty.
I got a copy of an MS Access VB script that selects an MDB file and then prints only one copy. My thought process was:
Open up a dialog box;
Select the printer;
Type in number of copies;
Print.
Currently, the portion of the original script I want to modify is:
[SQL query above this]
....
' Open form
Dim rs As DAO.Recordset
Set rs = db.OpenRecordset("select##identity")
Debug.Print rs(0)
Dim q As String
q = "transfer_id=" & rs(0)
DoCmd.OpenForm "Transfer Report", acNormal, , q, ,acDialog
DoCmd.PrintOut
...
[End If, End Sub, etc.]
This only prints out one instance of the report and the company does not have the ability to print out other copies at the same time. Since it is in the field, they don't have access to a copier but still need multiple copies.
One answer I found, by David-W-Fenton (thank you!), shows how to create a dialog box; Would the following script accomplish what I want to do? And, how do I add a portion to the dialog box to specify how many copies to print?
...
Dim varPrinter As Printer
Dim strRowsource As String
Dim q As String
Dim rs As DAO.Recordset
Set rs = db.OpenRecordset("select ##identity")
Debug.Print rs(0)
If Len(Me.OpenArgs) > 0 Then
q = Me.OpenArgs
Me.Tag = q
For Each varPrinter In Application.Printers
strRowsource = strRowsource & "; " & varPrinter.DeviceName
Next varPrinter
Me!cmbPrinter.RowSource = Mid(strRowsource, 3)
' first check to see that the report is still open
If (1 = SysCmd(acSysCmdGetObjectState, acReport, q)) Then
With Reports(q).Printer
Me!cmbPrinter = .DeviceName
Me!optLayout = .Orientation
End With
Me!txtPageTo = Reports(q).Pages
End If
End If
Public Function PrintReport(q As String) As Boolean
q = "transfer_id=" & rs(0)
' open report in PREVIEW mode but HIDDEN
DoCmd.OpenReport q, acViewPreview, , , acHidden
' open the dialog form to let the user choose printing options
DoCmd.OpenForm "dlgPrinter", , , , , acDialog, q
With Forms!dlgPrinter
If .Tag <> "Cancel" Then
Set Reports(q).Printer = Application.Printers((!cmbPrinter))
Reports(q).Printer.Orientation = !optLayout
Application.Echo False
DoCmd.SelectObject acReport, q
DoCmd.PrintOut acPages, !txtPageFrom, !txtPageTo
PrintReport = True
End If
End With
DoCmd.Close acForm, "dlgPrinter"
DoCmd.Close acReport, q
Application.Echo True
End Function

Here is a late reply, some times it may help others.
In order to open the print dialogue:
Place a command button for PRINT on the report, and write the code as below.
Private Sub CmdbtnPrint_Click()
DoCmd.RunCommand acCmdPrint
End Sub
Change the 'Display When' property of button to 'Screen Only'.
Open the report in 'acViewReport' view mode.
Click the PRINT command button, and the systems print dialogue box will be open. Set the parameters and print the report.

Check the documentation about the PrintOut method:
http://msdn.microsoft.com/en-us/library/office/ff192667.aspx
In your original script to modify, just add the Copies argument to the DoCmd.PrintOut statement, like:
DoCmd.PrintOut Copies:=x
where x is a variable representing the number of copies you want to print.
Reviewing the documentation for the DoCmd.OpenForm method,
http://msdn.microsoft.com/en-us/library/office/ff820845.aspx
I don't think the code you have can allow a user-input for the number of copies. I do not program in Access, but I'm certain there are other ways to allow user input at run-time. In Excel/PowerPoint we would use an InputBox or a UserForm.
I think you can use an InputBox in Access:
http://office.microsoft.com/en-us/access-help/inputbox-function-HA001228856.aspx

Related

prevent duplicates when passing values between two forms (with Args)

I have two forms: transfert Form with its subform and intransfert Form. I am using
DoCmd.OpenForm "intransfert", , , , acFormAdd, acDialog, Me!Text83
(where text83 is =[transfertasubform].[Form]![transfertadetailid] under
Private Sub Command78_Click()
in transfet form and
Private Sub Form_Load()
On Error Resume Next
If Me.NewRecord Then Me!trnrin = Me.OpenArgs
in intransfet form. intransfert form is based in transfertdetailquery. i wont to prevent passing text83 value more then one time
i tried to explain my problem and expect a help to prevent duplicates when used Arge
assuming trnrin is the name of a variable in your record source. assuming you mean that you want to avoid adding two records where trnrin has the same value and the user sent the same open args twice. assuming trnrin is also the name of a control in the detail section of the intransfert form.
'form load only runs when the form is opened so you have to close the form to pass new args
'but you can just move the same code to a button or whatever
Private Sub IntransferForm_Load()
If Len(Me.OpenArgs) > 0 Then
Me.txtBoxintheHeader = Me.OpenArgs 'the load event is the right place to set controls
'most of this code is to check if there is already an instance where trnrin = the OpenArgs in the record source
Dim lookedupArgs As String
lookedupArgs = Nz(lookedupArgs = DLookup("trnrin", "MyTable", "trnrin = " & "'" & Me.OpenArgs & "'"), "ValuethatisneveranArg")
If lookedupArgs = "ValuethatisneveranArg" Then
'Debug.Print "trnrin = '" & Me.OpenArgs & "'" 'note the string delimiters
'Me.trnrin = Me.OpenArgs 'this surprisingly works but will break easily and doesn't handle complex cases
Dim rs As Recordset
Set rs = Me.Recordset 'if recordset is bound to a table then table will also be updated.
'you can also bind to the table directly but you may need to call me.requery to show the changes
rs.AddNew
rs!trnrin = Me.OpenArgs
rs.Update
End If
End If
End Sub

Close subform, remove main form filter and go back to original record

I am opening a subform from my main form to allow data to be changed. Once the changes are made, I want to pass the data back to the main form. remove the filter, and go back to the original record. I have the Primary Key in the subform so I am passing it back. I used some code from another user's but it did not work not is my code. Any thoughts?
Private Sub cmd_close_Click()
Dim result As String
Dim ID As Variant
result = MsgBox("Save Geo Location?", vbOKCancel, "Save Geo Location")
If result = vbOK Then
Forms!frm_acct_select!GeoLoc_X = Me.txt_GeoLocX
Forms!frm_acct_select!GeoLoc_Y = Me.txt_GeoLocY
Forms!frm_acct_select.FilterOn = False
'this code fails immediately
With frm_acct_select.Form
ID = Me.txt_ParentID.Value
.FilterOn = False
.Recordset.FindFirst "ParentAccountID=" & ID
End With
'this code fails type mismatch criteria at the recordset.findfirst line
' With Forms!frm_acct_select
' ID = Me.txt_ParentID.Value
' .FilterOn = False
' .Recordset.FindFirst "ParentAccountID = " & ID
' End With
DoCmd.Close acForm, "sfrm_geoloc_update", acSaveNo
Else
DoCmd.Close acForm, "sfrm_acct_select_search", acSaveNo
End If
End Sub
Apparently, I still need to work on my string formatting.
Declaring ID as String was correct however I needed to add quotes to my code.
.Recordset.FindFirst "ParentAccountID = '" & ID & "'"

Opening form with DoCmd.OpenForm

I am troubleshooting and found that a button
does not seem to be working.
I want the button to print a report (from rptHerstelfiche) with the "IDDefect" as "Volgnr" (in rptHerstelfiche).
The code linked to that button.
Option Compare Database
Option Explicit
Private Sub Knop164_Click()
On Error GoTo Err_Afdrukken_technische_gegevens_Click
Dim stDocName As String
DoCmd.RunCommand acCmdSelectRecord
stDocName = "rptHerstelfiche"
'DoCmd.OpenReport "report name", acViewPreview,
DoCmd.OpenReport stDocName, acPreview, , "Volgnr=" & Me.IDDefect
Exit_Afdrukken_technische_gegevens_Click:
Exit Sub
Err_Afdrukken_technische_gegevens_Click:
MsgBox Err.Description
Resume Exit_Afdrukken_technische_gegevens_Click
End Sub
What you have looks good, but a few things:
Because the current reocrd is being sent to the report? Then the current reocrd may NOT yet have been saved. So what you see in the report will not show what you have in the form.
I suggest this code. and the "select" record is not required.
Dim stDocName As String
if me.Dirty = True then me.Dirty = False ' force data save
stDocName = "rptHerstelfiche"
DoCmd.OpenReport stDocName, acPreview, , "Volgnr=" & Me.IDDefect
The last line looks a bit "suspect", and should read like this:
DoCmd.OpenReport stDocName, acViewPreview, , "Volgnr=" & Me.IDDefect
Note the use of acViewPreview. And the editor SHOULD have suggested this contant.
Also, if Volgnr a number type column, or a string/text? You have to check this in the table designer.
If Volgnr is a text data type, then that line of code has to become this:
DoCmd.OpenReport stDocName, acViewPreview, , "Volgnr = '" & Me.IDDefect & "'"
note the requirement to surround the value with quotes.
So in summary:
check and use acViewPreview
force the record to be written to the table before you launch report
if you don't' write the record, then the report will show values not yet updated
check if the data type is a number/long/integer type or a text column
if a text column, then surround the value with quotes.

Me.Dirty moves currently selected record

I have an Access 2007 form that's giving me some headache.
I have a list of records that start as a combo box to pick a company and then a series of checkboxes to indicate the company's role.
If the user needs to add a new company, they'd pick the company name from the combo box, and then click the checkbox that indicates what role the company is playing. When the checkbox is checked, the form follows the following code to show a popup that captures additional information:
Private Sub chkOperationsAndMaintenance_AfterUpdate()
'DoCmd.RunCommand acCmdSaveRecord'
If Me.Dirty Then Me.Dirty = False
If chkOperationsAndMaintenance.Value = True Then
DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
Me.Requery
End If
End Sub
This code will save the record on the CompanyProject table to create the row. It then pulls the CompanyProjectID (PK of the CompanyProject table) so it knows which ID to feed the popup.
The issue I'm having is that on the Me.Dirty line (and also the above commented-out acCmdSaveRecord), the entire form saves and refreshes, moving the selected row to the first record (in this case, "Gamesa") rather than the newly entered record. So the ensuing popup is fed the CompanyProjectID of the first record rather than the newly-entered record, and it also reads the "checked" state of the checkbox from the first record rather than the one upon which the user is working.
I doctored the code to look like this:
Private Sub chkOperationsAndMaintenance_AfterUpdate()
Dim CPID As Long
Dim CID As Long
Dim rs As Recordset
Set rs = Me.RecordsetClone
CID = Me.CompanyID
'DoCmd.RunCommand acCmdSaveRecord'
If Me.Dirty Then Me.Dirty = False
CPID = DLookup("MAX(CompanyProjectID)", "CompanyProject", "cpProjectID = " & Me.cpProjectID & _
" AND CompanyID = " & CID)
rs.Find "[CompanyProjectID] = " & CPID
Me.Bookmark = rs.Bookmark
If chkOperationsAndMaintenance.Value = True Then
DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
Me.Requery
End If
End Sub
The idea with these alterations is that we'll get the FK from the parent form ("cpProjectID") and the CompanyID of the selection from the combobox, then save the record. Once the record is saved, we have the CompanyProjectID already stored, so then the rs.Find and Me.Bookmark lines will then select the record that matches that CompanyProjectID.
This sometimes works, and sometimes doesn't. Generally doesn't. In this case, I refreshed the parent form and the current form and attempted to add a new company and then click the "Owner" checkbox (which uses the same code as above, just a different checkbox ID) to see the Bookmark on the wrong row:
At this point, I'm not sure what to do. If I don't save the record (via acCmdSaveRecord or Me.Dirty=False) then I don't have a CompanyProjectID to send as the input parameter for the ensuing popup, but if I do save the record, then the form changes the record and the wrong parameter is sent and the wrong checkbox's checked state is read. I can't just use an arbitrary index to work off of (such as acNewRec), as the user might need to edit an existing row instead of adding a new one.
I tried the method in this post already: MS Access how to Update current row, move to next record, not first, but the find/bookmark isn't consistently working.
EDIT (12/15/2014)
I ended up going with the following VBA code:
Private Sub chkOperationsAndMaintenance_AfterUpdate()
Dim CPID As Long
Dim CID As Long
Dim rs As Recordset
Set rs = Me.RecordsetClone
CID = Me.CompanyID
If Me.Dirty Then Me.Dirty = False
CPID = DLookup("MAX(CompanyProjectID)", "CompanyProject", "cpProjectID = " & Me.cpProjectID & _
" AND CompanyID = " & CID)
Do While Me.CompanyProjectID <> CPID
If Me.CurrentRecord < Me.Recordset.RecordCount Then
DoCmd.GoToRecord , , acNext
Else
DoCmd.GoToRecord , , acFirst
End If
Loop
If chkOperationsAndMaintenance.Value = True Then
DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
Me.Requery
End If
End Sub
I feel like there has to be a better answer for this, but this is appearing to work right now. I have my end user/lab rat testing it at the moment, so I'll mark this complete if this pans out. I still think there has to be a better solution for this, but at the moment, this solution is able to capture the requisite ID to pass to the popup, and it selects the appropriate row after this ID is captured.
Have you considered saving the current position - like Me.CurrentRecord, then after the save reposition to the desired record. As an example, you could add a 'Before' or 'After' Insert to save the position, then later reposition. See the following:
Option Compare Database
Option Explicit
Dim lCurRec As Long
Private Sub Form_AfterInsert()
lCurRec = Me.CurrentRecord
Debug.Print "After Insert, Current: " & Me.CurrentRecord
End Sub
<<< YOUR SUB>>>
DoCmd.GoToRecord acDataForm, Me.Name, acGoTo, lCurRec
This code will work when adding a new record as well as when editing an existing record:
Private Sub chkOperationsAndMaintenance_AfterUpdate()
Dim c As Long
Me.Dirty = False
If chkOperationsAndMaintenance Then
DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
c = Me.CurrentRecord
Me.Requery
DoCmd.GoToRecord , , acGoTo, c
End If
End Sub
I am guessing that your popup form does things that are specific to Operations & Maintenance, and does not change the values of any of the checkboxes on the main form. If this is the case, you don't need a Requery at all, and the code can be simplified:
Private Sub chkOperationsAndMaintenance_AfterUpdate()
Me.Dirty = False
If chkOperationsAndMaintenance Then
DoCmd.OpenForm "OmPopupForm", , , "CompanyProjectId = " & Me.CompanyProjectID, , acDialog
End If
End Sub

Using query yes/no field for checkbox record source?

First of all, you start with a form named LoginF. Once you choose your login ID, and password; and log in it takes data from the table LoginIntoT for the login ID you chose, and creates a query with said data using this code:
On Error Resume Next
DoCmd.DeleteObject acQuery, "IsAdminQ"
On Error GoTo Err_LoginBtn_Click
Dim qdef As DAO.QueryDef
Set qdef = CurrentDb.CreateQueryDef("IsAdminQ", _
"SELECT IsAdmin " & _
"FROM LoginInfoT " & _
"WHERE EmployeeID = " & LoginCmBx.Value)
Exit_LoginBtn_Click:
DoCmd.Close acForm, "LoginF", acSaveNo
DoCmd.OpenForm "MenuF"
Exit Sub
Err_LoginBtn_Click:
MsgBox Err.Description
Resume Exit_LoginBtn_Click
From there in that query after you log in is only 1 column and 1 row; meaning one piece of data. This data is a yes/no field which is either Yes or No depending on who you logged in as.
On the form it opens after you click the login button it has a logout button. The logout button brings you to the previous login form, and deletes the query (IsAdminQ).
What I am trying to do is attach a yes/no button on a form to take that data, and output if it's yes or no on the query.
I've tried putting this in it's control source:
=[IsAdminQ].[IsAdmin]
Though what that does is output it as a filled in square instead of a checkmark or empty. I have triple state set as no.
How would I attach the checkbox to the query so if the data says yes, then it's a check mark and if it says no it is an empty box?
I understand you.
"On the form it opens after you click the login button it has a logout button", we call it frmLogout. You shall do this:
Solution I:
frmLogout.RecordSource = "IsAdminQ"
Then for your checkbox named MyCheckbox, we set it this:
Me.MyCheckbox.ControlSource = "IsAdmin"
You cannot use this:
Me.MyCheckbox.ControlSource = "[IsAdminQ].[IsAdmin]" ' <= here it's impossible.
Solution II:
On the form frmLogout without setting IsAdminQ as .RecordSource,
In a Public Module, insert this:
Function GetLoginStateIsAdmin()
'
Dim rst As DAO.Recordset
Set rst = CurrentDb.OpenRecordSet("IsAdminQ")
GetLoginStateIsAdmin = Nz(rst(0), False)
Set rst = Nothing
'
End Function
Then in the private module of any form, as frmLogout:
Private Sub Form_Open(Cancel As Integer)
'
Me.MyCheckbox.Value = GetLoginStateIsAdmin()
'
End Sub
Set it in addition in design mode:
Me.MyCheckbox.TripleState = false
And check also if the query IsAdminQ has been successfully created in the login step. And open it in Access Navigation Pane by double-clicking on it. And see the value of the query.