I have a multiple VBA forms, the first form takes user's name from a combo box and saves it in a global variable, code is below :
Option Compare Database
Public emplID_global
Private Sub OKLogin_Click()
If Not IsNull(Me.Combo_emplID) Then
emplID_global = Me.Combo_emplID.Column(1)
DoCmd.Close
DoCmd.OpenForm "NavFrm", acNormal
End If
End Sub
Now in my other form I have a combo box in which I want to auto-populate the valueof that variable, on load of form, which i saved using previous form, below is the code :
Private Sub Form_Load()
Me.AdvName = emplID_global
Me.DataForm.Form.Recordset.MoveLast
End Sub
but it is not working, It is not doing anything. I want to use this kind of code in all the forms.
Can someone please suggest what is the mistake in my code, i am fairly new to VBA. Thanks in advance :)
Add a field to your underlying table for the owner of that particular record. (I just called it Owner.)
Add the following code to your form:
Private Sub Form_BeforeInsert(Cancel As Integer)
Owner = Environ("username")
End Sub
Private Sub Form_Current()
Dim editable As Boolean
if nz(Owner,"")="" then
editable=true
else
editable = (Environ("username") = Owner)
End If
Form.AllowDeletions = editable
Form.AllowEdits = editable
End Sub
This is a fairly generic solution that does the job. Environ("username") returns the user's windows username. This is not necessarily all that secure. A person could go to the command prompt and edit the username environment variable so that they appear to be another person. This will definitely not keep out the NSA or anyone else with a little computer knowledge and bad intentions. But it will keep the honest people honest.
Explanation:
The BeforeInsert runs as a new record is being saved. In this case, it sets the record's Owner field to the user's Windows username.
The OnCurrent portion runs every time a new record is displayed. The code will check to see if the current Windows username matches the username stored in the record's Owner field and set the forms AllowEdits and AllowDeletions flags accordingly. Also, if the Owner field is null (as in the case of a new record), editable will be set to true. If you wanted to really emphasize the fact that the user shouldn't be changing things, you could also enable/disable the individual text boxes...
TextBox1.Enabled=editable
ComboBox2.Enabled=editable
... etc.
Simple solution. Keeps honest people from overwriting each others' work. I use this approach a lot.
Related
I am writing here because I cannot seem to find the answer on the internet.
Context of my sub and userform : I have several pivottables in the same sheet in a workbook.
These pivottables may have random names given by other users changing them unintentionally or not knowing the names are essential to the rest of the code. This is why i created a userform which has on one side the ideal name of each pivottable, and on the other side, comboboxes with the current names, like so:
pivottable dealing with x // combobox with all current names (user has to choose which one of the current names corresponds to the this pivottable)
pivottable dealing with y // combobox with all current names (user has to choose which one of the current names corresponds to the this pivottable)
pivottable dealing with z // combobox with all current names (user has to choose which one of the current names corresponds to the this pivottable)
and finally a button "VALIDATE"
here is a screenshot of my userform : enter image description here
WHAT I AM TRYING TO DO :
since the user has to inform the userform which pvttable corresponds to which title, i have written :
userform1.show vbmodeless
so that the user can go check the current titles of the pivottables and associate them with the correct one. Because I have put the vbModeless, the sub does not wait for the user to validate and thus fills the title with nothing or blank as nothing from the combbox has been chosen since the user hasn't had the time yet. Therefore, I want to signal that once and only once i clicked on "valider", then the sub changes the current titles to the ideal titles (can only do in the sub and not in the userform because i actually use an array that is subject to changes in the ideal names, and I can't put it in the userform because it is defined above in the sub, ican't pass it over to the userform). I am triyng to use something like :
if userform1.commandbutton1.click = true then
'and put pvtnames = userform1.combobox1.value
(but i am alright with the pvtname part). IS THERE A WAY TO CODE THE BUTTON.CLICK PART ? thank you ever so much for your help, i am sorry for the long message
I am creating a form with multiple subforms. The way that it works is that:
the user selects a BASIC at the top
that makes the text fields MACHINE NAME, TOOL SEQUENCE NO., TOOL NO., and TOOL DESCRIPTION change.
The text fields MACHINE DESCRIPTION and MACHINE TYPE at the bottom depend on the MACHINE NAME, which means that
as soon as the machine name changes, the machine description and type should immediately change.
I used queries to describe the relationship between BASIC and MACHINE NAME and between MACHINE NAME and MACHINE DESCRIPTION.
What ends up happening is that when I change the BASIC, the MACHINE NAME changes but the MACHINE DESCRIPTION doesn't change immediately. The MACHINE DESCRIPTION changes only after the second time I change the BASIC (and it changes to the MACHINE DESCRIPTION matching the MACHINE NAME selected previously).
I believe this is because the MACHINE DESCRIPTION waits until the MACHINE NAME is changed to requery the data, which would explain why the value for the machine description is "delayed" one click.
How do I make the MACHINE DESCRIPTION change as soon as the MACHINE NAME changes?
I am open to using VBA code if it is required.
VBA is often known as a trigger language as it is often used in response to events in the application which for the MS Access object library includes AfterUpdate, OnOpen, ButtonClick, etc. in GUI objects such as forms and reports, and can even extend to called functions in macros and modules.
Because you have subforms showing "snapshot" resultsets to screen derived from queries with parameters pointing to form values, consider actually requerying subforms after saving your user entry with Form.Requery for newer "snapshots". In fact, it is a wonder any subform was updated without Form.Requery!
Place the below VBA code in an AfterUpdate event behind your BASIC textbox. Do not repeat Public Sub and End Sub. This will loop through all subforms using the Forms.Controls property of your main form after you update values in BASIC entry.
Private Sub BASIC_AfterUpdate()
Dim ctrl As Control
' SAVE CURRENT RECORD
DoCmd.RunCommand acCmdSaveRecord
' REQUERY ALL SUBFORMS
For Each ctrl in Me.Form.Controls
If ctrl.Type = acSubform Then
Me.Form.Controls(ctrl.Name).Form.Requery
End If
Next ctrl
Set ctrl = Nothing
End Sub
I have a form set up for data entry for new orders. When entering a new order a customer can be selected from a combo box. Shipping address, zip, state, etc. are in each customer record.
When a new order is made, the shipping destination may or may not be the the address attached to the customer.
I would like to add a check box to the form that when checked auto populates the shipping information fields to the customer's information. What would be the simplest way to achieve this?
Thanks
You should use the On click event of the checkbox.
Private Sub Checkbox_Click()
If Me.Checkbox = True Then
Me.TextboxShipDest.Value = Me.TextboxShipAdress.Value
Else
Me.TextboxShipDest.Value = Null
End If
End Sub
Detailed description inside
Background
I have a spreadsheet with a Pivot table ("PT") that many users will access through my company's web portal. The users are assumed to have little to no experience with Excel and little to no tolerance for "additional steps". So user interaction apart from normal pivot operation won't work.
I am running SQL Server 2008 and using a stored procedure to generate the data. I have to use a stored procedure because I need to be able to pass along a parameter from Excel (this is not ideal but I have numerous safeguards).
Chronological Order of Factors/Solutions
Complication 1
A PT cannot directly connect to a stored procedure like it can tables etc.
Solution This means that the data must first be imported into a table (which can connect to a stored procedure) and then this table will be the source for the PT.
Complication 1A
When the table refreshes (updates data connection) the PT will not refresh itself because it has no trigger event.
Solution: Use VBA and specifically the worksheet change event on the table's sheet module to force refreshes on PT. This works great and all was working 100%.
Complication 2
When a PT whose is within the same workbook and this workbook is opened from a remote location (web portal), you will get an error that looks like "Error 1004: Source file not found". The PT tries to use the path of the workbook to connect to its source but it sees the temporary URL as its path.
Solution: Instead of directly refreshing the PT using PivotCache.Refresh, RefreshTable use Activeworkbook.RefreshAll which for whatever reason does actually work when the former gave me the Error 1004.
Complication 3
So now I need to now detect a change in the table and then use Activeworkbook.RefreshAll. But despite using Application.EnableEvents = False and even setting a boolean to prevent the change event from kicking in when the Activeworkbook.RefreshAll is executed, I am getting an infinite loop.
Worksheet Module:
Private blnAbort As Boolean
Private Sub Worksheet_Change(ByVal Target As Range)
If blnAbort = True Then Exit Sub
blnAbort = True
Call Refresh
blnAbort = False
End If
End Sub
Standard Module:
Public Sub Refresh()
Application.EnableEvents = False
ActiveWorkbook.RefreshAll
Application.EnableEvents = True
End Sub
Possible Solution that caused another problem:
It seems like the Activeworkbook.RefreshAll was being executed and then the macro just continued on while it was still refreshing. This seemed to be causing the Enable_Events event and blnAbort to be reset just in time for something to refresh and trigger a change and the whole thing started again. I changed the data connection property BackgroundRefresh to false.
However, now I am getting the error Method 'RefreshAll' of object '_Workbook' failed and the debug is just jumping to Activeworkbook.RefreshAll which is not helpful.
Any ideas?
How are you calling the refresh of the source table? If the user refreshes it via a button then you can just force a refresh of the pivot table's pivotcache...
in the worksheet code-module:
Private Sub BtnRefreshData_Click()
'// Insert the "refreh" routine or call a procedure to refresh the
'// data from the stored procedure here..
'// Once the data is done being refreshed, manually refresh the pivot cache
'// for the pivot table. The code looks like this:
Sheet1.PivotTables("MyPivotTable").PivotCache.Refresh
'// If you have a lot of pivot tables to refresh from your "source" data-table
'// then you can always just do a foreach loop...
Dim sht1 As Worksheet: Set sht1 = Sheet1
Dim pTable As PivotTable
For Each pTable in sht1.PivotTables
pTable.PivotCache.Refresh
Next pTable
End Sub
Let me know if this helps, or be more specific as to why something straight forward like this won't work and ill do my best to try again. If it does work, let me know! thanks, Brian
UPDATE:
So in response to your comments: From what I can tell it sounds like really the only issue you have is the infinite loop created by interwoven events (event that refreshes the pivot table calls the change event, which refreshes the pivot table, etc. etc, etc...). I think the easiest solution for you at this point is to disable all events when the refresh event takes place, which shouldn't fire off the unwanted event (causing the loop). Before the code that refreshes the pivot table put the following code:
'// Start Code Snippet...
Application.EnableEvents = False
'// Do your refresh routine here....
Application.EnableEvents = True
'// End Code Snippet
Does this help? If not I'll try again :) ... thanks, Brian
SQL Server/VB2010 newbie. Fighting the learning curve on two fronts.
I am creating a UI in VB2010 to a SQL Server database that will allow users to edit tables in the database. Since the tables in the database may change (new ones added, or obsolete ones deleted) as the project develops, the table names are dynamically added to the sub menu, as shown in the screen cap below:
Then I use the AddHandler function to run the click event sub. That works fine, but what I need to do is grab the actual text of the submenu item ("VehicleList", "Maintenance", etc.) to use in the SQL SELECT string to open the selected table in the database, like so:
"SELECT * from [selected_menu_item] WHERE yada, yada"
I've scoured the internet looking for this, but if it's there, I can't find it. Tried many ways, but I either get the top menu item ("Table") or the last item on the list, or sometimes just a blank line.
Preferable would be to get the actual names, but even if there was an index value, I could use that to reference an array of the table names.
Can anyone help?
Thanks!
The answer is to use the "ByVal e As ToolStripItemClickedArgs" argument in the handler, like this:
Private Sub MenuItem_click(ByVal sender As System.Object, ByVal e As ToolStripItemClickedEventArgs)
Debug.WriteLine(e.ClickedItem.Text)
End Sub
Found this at http://msdn.microsoft.com/en-us/library/system.windows.forms.toolstripitemclickedeventargs.clickeditem.aspx
It works exactly as I need it to!