I am very new to VBA and have been searching to try to figure this out but with no luck.
I am trying to make a form that pops up and has a bunch of different fields to enter and then when the form is submitted, the information is input into separate, specific cells. Also, once the information is input into the cells, it needs to be printed for our records. One last thing to add is that I need some of the fields to disappear if they are empty on the form so that they do not print.
I have a lot of fields for this and all that I have found is how to insert into a new row. If this can be done it would help me out a LOT. If anyone can point me in the right direction then I may be able to figure some out on my own I am fairly literate in HTML so I am able to do some coding.
The fields I have to enter:
Deposited By:
Number of Deposits:
Total Checks:
Electronic Deposit Number:
Electronic Deposit Number:
Manual Deposit Number:
Deposit Amount:
Deposit Amount:
Deposit Amount:
Houston Depos:
Dallas Depos:
Austin Depos:
Houston Video:
Dallas Video:
Austin Video:
Houston Records:
I will also need to add a button or make the form popup whenever the spreadsheet is opened so that the information can be entered but I believe that may be a little easier to figure out. Along with pre-filling the form with the information already on the page so that it can be edited.
I'll try to answer a few of your questions that you had so hopefully you can write some of your own code:
Form popup whenever the spreadsheet is opened (Placed in the ThisWorkbook code):
Private Sub Workbook_Open()
UserForm1.Show
End Sub
You can also add a button in the Worksheet and assign it a macro which uses UserForm1.Show.
For the pre-filling the form with information from the sheet use commands like this (Placed in your UserForm code:
Private Sub UserForm_Initialize()
txtDepositedBy.Text = Sheets("Sheet1").Range("A2")
End Sub
To print your sheets use the Sheets.PrintOut Method:
ActiveSheet.PrintOut
'or
Sheets("Sheet3").PrintOut
It has these inputs:
.PrintOut(From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate, PrToFileName, IgnorePrintAreas)
To take your inputs from text boxes and other elements, you can use commands like these:
ActiveSheet.Range("A1").Value = TextBox1.Text
'or
Sheets("Sheet3").Range("B2").Value = ComboBox1.Text
This should cover a lot of your questions. If you have anymore just let me know and I'll add to the post.
Related
I'm working on a record keeping system for the animal room in our small museum using google sheets. Some of our animals eat every other day.
I have a function that puts the date at the top of the daily sheet. I need a function which will look at the date and show a checkable box if it's an even date or a line if it's an odd date (or vice versa). But I can't get the check box into the "or" function.
Super grateful for any help!
try:
=IF(ISEVEN(A1); "☑"; "☒")
update:
workaround demo
I've set up a word form with different sections, each section to be completed by a separate person.
Each section of the form includes a combination of dropdown lists or free text fields set up using named Content controls.
At the end of each section there is field for the staff member to record their name, the date (calendar icon), and a command button with an associated macro to save the form and protect the data once that section has been completed.
While this enables the data to be protected it does not prevent person A from completing the form and entering person B's name. Note, this would not be expected, but traceability is required for regulatory purposes.
I would like to update the macro to protect the sections, save the file (currently working), and then immediately after saving, have the macro populate another field directly under the manually entered name and date with the Microsoft advanced properties of Last Saved By and the date and time. This would confirm the user.
My macro below (InsertMSSavedDetails()) will extract the Microsoft required data, but only if I manually click on the form and run the macro, and then it saves wherever I click on the form and won't save to the named ContentControl box. I'd like to automate this last step so that it is not reliant upon the user and the data is associated with particular section.
My form includes the following code:
Module
Sub ProtectFieldsSections2()
' protects Sections 1 and 2
If MsgBox("Do you want to Lock and Protect this section from further editing?", vbYesNo) = vbNo
Then Exit Sub
Dim sec As Section
Dim cc As ContentControl
Set sec = ActiveDocument.Sections(2)
For Each cc In sec.Range.ContentControls
cc.LockContents = True
Next cc
End Sub
This document:
Private Sub CommandButton2_Click()
ProtectFieldsSection1
ProtectFieldsSection2
ActiveDocument.Save
End Sub
Current code for Adding Microsoft data - which technically works, but not in the manner I need:
Sub InsertMSSavedDetails()
'
ActiveDocument.SelectContentControlsByTitle ("MSSavedDetails")
Selection.TypeText Text:="Check data: "
Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:= _
"LASTSAVEDBY ", PreserveFormatting:=True
Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldEmpty, Text:= _
"SAVEDATE \# ""d/MM/yyyy h:mm:ss am/pm"" ", PreserveFormatting:=True
End Sub
Second issue with the above, is that it would only need to be added the once, when Sub CommandButton2_Click is first selected. If I were to update the Sub CommandButton2_Click, how would I stop if from repeating the cycle of save, insert Microsoft data, save, insert Microsoft data?
NOTE: Use of word vs PDF form. Presently, the form is used in word format, converted to PDF, and electronically signed, however this does not allow others to add their information to the remaining sections. Adobe LiveCycler has been used to design PDF forms but there were issues with maintaining images and graphs, and there were other issues experienced with the Adobe reader, so the option is to remain with word.
Thank you.
Not sure I have completely understood the problems, but
The problem with inserting the field codes LASTSAVEDBY and SAVEDATE is that unless you "lock" them, their values will always reflect the most recent save. Also, if you want the fields to go in a content control, you have to use a rich text content control.
Perhaps better to
save the document
get the underlying property values (the ones that LASTSAVEDBY and SAVEDATE display) and insert them
save the document
If you have content controls named (say)
Section1LastSavedBy
Section1SaveDate
Section2LastSavedBy
etc.
then
you know which commandbutton the user clicked so you know which section you are dealing with
your code can then look something like
Private Sub CommandButton2_Click()
ProtectFieldsSection1
ProtectFieldsSection2
With ActiveDocument
.Save
.SelectContentControlsByTitle("Section1LastSavedBy")(1).Range.Text = _
.BuiltinDocumentProperties("Last Author").Value
.SelectContentControlsByTitle("Section1SaveDate")(1).Range.Text = _
format(.BuiltinDocumentProperties("Last Save Time").Value,"D/MM/YYYY h:mm:ss am/pm")
.Save
End With
End Sub
If you want to construct the content control names programmatically based on Section number, you can.
If you want to lock the content controls against further editing, you can.
I am not sure what problem you are encountering here:
"Second issue with the above, is that it would only need to be added the once, when Sub CommandButton2_Click is first selected. If I were to update the Sub CommandButton2_Click, how would I stop if from repeating the cycle of save, insert Microsoft data, save, insert Microsoft data?"
unless you are using a Save event. If that's the problem we could revisit that part.
It's pretty difficult to stop people tampering with data in Word, but personally I would consider saving copies of these values in, e.g., a Custom XML Part (not mapped to the controls) or Document Variables - possibly also encrypt them - you can use Windows crypto APIs for that.
Incidentally, I suspect the problem you have with your existing code is that .SelectContentControlsBYTitle doesn't Select the controls in the normal Word sense. It just returns a collection of controls with that name.
I am a research student working on an access database where I have created a continuous form that is to be used in a sort of scrolling electronic health record format. The header includes information about the patient and the continuous form aspect is a series of patient visits. In the header, I have a few subforms, which populate based on linking on the patient_ID number which is posted in the header (generated by vba macro such that previously reviewed patients aren't revisited). These subforms seem to significantly lag such that they the results from the previous patient stick around going into the next one. The subforms contain user-selected pertinent data. Each form has its own table. They are linked primarily based on patient_ID.
I have tried:
macro on the header detail: on click, refresh. - seems to work, but not very elegant/intuitive
macro on the main form - same as above but on load, click, got focus, lost focus, open, activate -- none of them seem to do anything.
forced requery via vba (see below) on opening/etc of the form. Neither way has worked. Tried to run these on opening the header form.
Public Function RequeryMain()
Dim frmMain As Form
Set frm = Forms("FRM_continuous_reports_patient")
frm.Requery
End Function
Public Function RequeryHeader()
Dim frmHeader As SubForm
Set frmHeader = Forms("FRM_continuous_reports_patient").FRM_continuous_header_working
frmHeader.Requery
End Function
In the end, it is frustrating for users to have to click to clear the form for new entries. It works otherwise.
The end goal is for the form to open and have all the subforms load based on the newest patient_ID. This would likely have to involve a staggered load: (1) VBA script selects the next patient based on certain characteristics and passes the patient_ID to the main form; (2) load main continuous form based on patient_ID submitted to it; (3) load the header subforms and any pertinent data within (although should be blank for the first time these are seen); (4) on completion, back to (1).
From what I understand, this is already how it is working, however the subforms are loading too quickly? How can I fix this?
Hopefully someone can help explain how to remedy this/correct any misunderstandings I have about the mechanics of forms.
I know this will sound odd, but subforms actually load before parent form. Lag in subform display is not something I have encountered. Code should not be needed and likely will not correct. Must be something about the form/subform design, maybe their RecordSource. Would have to examine db to determine.
It is not necessary to create form objects in VBA just to requery. Is code behind the main form? Me.Requery will be enough for the main form. I always give subform container a name different from the object it holds, like ctrPatient. Then just Me.ctrPatient.Requery.
Why not put subforms in Detail section?
To answer your questions, and provide a condensed version of the logic referenced at: https://accessexperts.com/blog/2014/01/07/delay-loading-subforms-in-access/
is to:
In design view, set your subform SourceObject to "" (and save your form)
When you are ready to show the subform, just execute: Me..SourceObject = ""
When you are ready to navigate to the NEXT patient, clear the subform link: Me..SourceObject = ""
Now that should solve the issue of out of sync data between the main and sub.
You don't need to use the CASE statements, but they operate as if you had a bunch of "If" / "ElseIf" all nestled together -- except the CASE makes it easier to follow. It basically gets a value from a variable (i.e. Select Case MyVariable); then checks to see if it equals what you want (Case 1, Case 2, etc.), and if so, does whatever you code.
I am storing data on eye colour, for example. I have a table about containing 100's of contact details for people in many different local authorities (LA). These contact details change frequently and a team of users will update the table when necessary.
I want to make a split form to do this for us. The idea is to be able to use a drop-down menu for both the LA (location) and the eye colour in the form, to filter the table below to show only the relevant contact details.
The user can then quickly find the correct record, click on it, this will autofill the rest of the form, and any details can be changed and then saved.
My problem is that I can't make the form robust enough to not erroneously overprint existing contact details, and I can't get a two step filter process to work. The contact details for previous records don't seem to clear, even when filtering for different places, so it is easy to muddle up and overprint records.
Here is a screen shot of the form so far:
example of the split form, filtered for records from Broadland but not by colour yet
Here is the VBA
Option Compare Database
Private Sub Detail_Click()
End Sub
Private Sub LA_AfterUpdate()
Me.Filter = "[LA] = " & Chr(34) & Me.LA & Chr(34)
Me.FilterOn = True
End Sub
Private Sub UpdateRecord_Click()
RunCommand acCmdSaveRecord
Me.Requery
End Sub
If anyone could help with:
How do I filter for colour as well as place?
How can I make the form save the amended record and then clear the form so that no records are overprinted?
If I filter for one thing and click to bring up the full record, how can I make the form drop this record and change to a different one if I decide to re-filter and pick a different record
I would be very grateful! Thank you in advance.
Answer for question 1
1.Open form Design View
2.Click at the table at the bottom of your form
3.Open Property Sheet for that table
4.Open Data at Property Sheet. You will see Link Master Fields and Link Child Fields. Click at ... sign and it will appear Subform Field Linker. Fill in the master and child field's column as you desired (eg. LA, color, place). Then the form will show the result.
Answer for Question 2
You have to use vba code under UPDATE RECORD button. For clearing the form after saving the record, use DoCmd.OpenForm "your form name",,,,acFormAdd
Example answer for question 2:
Private Sub TESTSAVE_Click()
If MsgBox("Changes have been made to this record." _
& vbCrLf & vbCrLf & "Do you want to save these changes?" _
, vbYesNo, "Changes Made") = vbYes Then
DoCmd.RunCommand acCmdSaveRecord
DoCmd.Close
DoCmd.OpenForm "NewATN2",,,,acFormAdd
Else
DoCmd.RunCommand acCmdUndo
End If
End Sub
I am building a Booking model in Rails 3.2.3 where a user steps through several form-screens of choices. If the form exactly mirrored the underlying model I know I could use a gem (e.g. Wicked gem) to build a multi-step form. The issue I am having is that on one of the form-screens there are multiple options for the user and within each of those options there are multiple options coming from an external web-service. In other words, on step 2 of the multi-step process, the form presents the user with many options of Rates from our database and for each Rate we have multiple additional options from the web-service. So a user would need to choose one of the options from the web-service (radio buttons) and then make a selection of their Rate of choice. This is then repeated multiple times on this page (although the user can only choose one radio-button option from the web-service and one Rate).
Where I am unsure of best practice is that I can display the multiple options from the web-service as radio buttons but there is a Hash of values associated with each of those options and hence with each of those radio buttons.
So, the question is, should I be attempting to pass that Hash as a param to the next step of the form process or should I be making that into an object and passing that or something else entirely!
I know this is a long explanation but I feel it's a critical point in the design of this workflow and I want to get it right.
Many thanks in advance,
J.
EDIT
Thinking it through again, the initial problem is how to represent a series of radio buttons when each radio button represents many values as opposed to say an id (in this instance each radio button represents a hash of values from the external web-service). Should the hash be made into an object and this passed instead - something along those lines?
I figured this out. On inspecting the "hash" coming back from the external web-service, I noticed that date fields were not in quotes, e.g.
:departs=>Wed, 21 Aug 2013 10:40:00 +0000
whereas all the other fields were in quotes. This made me a little suspicious. So in the end I used to_json on the returned hash:
response_hash_from_webservice = data.to_json
In the form I then used:
JSON.parse(response_hash_from_webservice).each do |nested_item|
# Access elements like so
... nested_item['company_name'] etc ...
end
However I needed to post this nested_item through to a next step of the form (as a radio button) and it only worked by again using to_json.
<%= radio_button_tag 'nested_item', nested_item.to_json %>
I could then post this value or put it in the session and on the following form page use:
require 'json'
hash = JSON.parse session[:nested_item]
And then access the values as normal:
<%= nested_item['company_name'] %>