Access Form Scrollbars won't disappear when not needed - vba

I have multiple continuous sub-forms in a single parent form. When the number of records in the subform is small enough that the scrollbar is not need, it disappears but leaves behind a white space where it would usually be if drawn. If the subform originally is opened with the small number of records, there is no graphical issue. Seems to be a refresh/repaint issue but that isn't working. Any pointer in the right direction would be greatly appreciated! Have read that it may have to do with margins/anchors but all steps down that path have turned up nothing.

Another way to handle this is to essentially reload the sub-form by...
Save the SQL string representing for the recordsource property of the sub-form to a string variable.
Set the SourceObject property of the sub-form container to "".
Set the SourceObject property of the sub-form container back to the original name.
Set the recordsource property of the sub-form = to the string variable in step 1.
This should remove the grey area previously occupied by the scroll bar.

Check the record count. Set the scroll bar accordingly...
Me.Scrollbars = 0 ' to not show them.
Me.Scrollbars = 1 ' for horizontal only
Me.Scrollbars = 2 ' for vertical only
Me.Scrollbars = 3 ' for both horizontal and vertical

Related

How to get values from controls on tabstrip in VBA?

In different tabs of a tabstrip I have input values which are different in each tab. I need to write a code which takes all these values and do some work like sums up the values of each tab on button click.
Can anyone help me do this? In my code when I input value at a textbox of one tab it also changes the value of all other tabs and hence cannot receive different values of each tab. Any idea, please?
Multipages vs Tabstrips
A multipage is an object with "pages". Each page can hold it's own collection of controls which can then be referenced either directly or through the containing page object.
A tab strip is an object with "tabs". Unlike a "page" object, a tab does not have it's own controls. Instead, there are only the original controls, visible for all "tabs".
Programmatic differences
Since a multipage has a different set of controls for each page, there is very little housekeeping required. The selection of a page affects which controls are visible, and the controls automatically retain values assigned to them (as expected).
For a tabstrip, since there is only the initial set of controls, there is a lot of housekeeping required in the code. The selection of a tabstrip does not have any automatic effect on the values in the controls. Instead the controls act as would be expected if they were not in the tab strip at all.
Tabstrip Solution
Set up a variable (array, collection, dictionary) that can be used to hold the various values of the controls. Then, in the TabStrip_Change() event, store the previous value, and reset the control for the new tab (or fill in the value the new tab last held).
I recommend adding a userform level variable Dim old_tab as Long which you can set to the current page at the end of the TabStrip_Change() event. (This is useful for retrieving previously filled values for the correct tab).
For my sample code, I will be using an array. However, since arrays are not very flexible with changing lengths, you can also look into using either a dictionary or collection, if desired.
For the userform pictured below, the following code causes the single textbox to act as though there is a different textbox per tab. It also saves the values whenever the tabstrip changes. (Note: if you then use the saved values for the calculation, remember to update the value for the current tabstrip first.)
Option Explicit
Dim old_tab As Long
Dim textValues As Variant
Private Sub TabStrip1_Change()
textValues(old_tab) = TextBox1.Value 'Saves the old value
TextBox1.Text = textValues(TabStrip1.Value) 'Updates value to reflect tab change
old_tab = TabStrip1.Value 'updates tab # variable
End Sub
Private Sub UserForm_Initialize()
ReDim textValues(0 To TabStrip1.Tabs.Count - 1) 'tabs are zero-based, so count is always one more than the maximum tab value
old_tab = TabStrip1.Value 'Ensures that the first value will be saved to correct location at the tab change
End Sub

Excel Form buttons remain in same place, but TopLeftCell is different (all after parent row is unhidden)

Cutting right to the chase, I have a tab with 4 Excel Tables stacked on top of each other. Each row has its own "up" and "down" buttons in the column to the left of the table, like this:
I shrunk the buttons to fit within the same cell (rowheight of 20). This allowed me to use the cell's TopLeftCell.Row property as follows: When clicked, stuff from the button's row is copy-pasted to the row above/below. This is the basic code:
currRow = ActiveSheet.Shapes(Application.Caller).TopLeftCell.Row
If InStr(Application.Caller, "Up") > 0 Then
Move_Project_Up currRow
Else
Move_Project_Down currRow
End If
When the user gets to this tab, any empty table-rows are hidden (with a Rows(rr).EntireRow.Hidden = True). The buttons Move and size with cells so they are automatically hidden). All visible buttons work as expected. However, sometimes a user wishes to move a project from the top of one table "up" to the bottom of the above table (i.e. to a currently hidden row). You can imagine wanting to move data from row 312 "up" to row 244 in the image below:
The code successfully makes the move and unhides the row. HERE'S THE PROBLEM: when the row is unhidden, the buttons are dark gray and their TopLeftCell.Row is wrong:
They are NOT disabled. When clicked, they still trigger the assigned macro. However, I can see from a Debug.Print that their TopLeftCell.Row is not necessarily the row they are actually in. In the image above, BOTH SETS OF BUTTONS have a TopLeftCell.Row of 97. That's correct for the first set, but not the second.
Any thoughts on why this might be happening? I suspect it has to do with the unhiding of the rows, and/or the fact that there's a lot happening on this tab (e.g. over 10,000 array formulas).
Thanks in advance!
As one commenter (jkpieterse) suggested, setting the .Top property of the "broken" buttons to the .Top value of a cell in the same row worked!

Set the caption of a frame in a continuous form

I would like to set the caption of a frame dynamically inside a continuous form.
So far I am doing the following:
Private Sub Form_Load()
Me.myFrame.Caption = Me.created_date
End Sub
This only sets the value of the first record for all Frames. I want the frame to have the "creation_date" of each entry of my table.
What do I have to do to make the caption dynamic ? The Frame control does not have a "Data" binding like textfields, so I think that I have to set it programmatically.
Set the Record Source of your form to whichever table/query you're using.
Add the Option Group frame to the form and delete the label.
Place a text box where the deleted label was and format as needed.
Give the text box a Control Source pointing to your date field and it should just work.
You can't do this directly.
Unbound controls like the frame caption by definition have the same value for all records in a continuous form.
The only way is to use a bound control (textbox) as workaround, as shown by Darren.

Do not show partially visible rows in datagridview

I try to implement the following in winform vb net project (I see this work in an app written in delphi).
I wish to hide or set visibility to false of the bottom row that partially visible in dgv that is docked to fill.
I tried to implement something like this:
DataGridView1.Rows(DataGridView1.DisplayedRowCount(true) - 1).Visible = False
I think it should be called during DataBindingComplete and Resize/scroll events, but it doesn't work.
Do you have any ideas / solutions?
So what I use on one of my datagridviews is:
Dim ind As Integer = 0
ind = DataGridView1.Rows.Count - 1
DataGridView1.Rows(ind).Visible = False
which hides the last displayed row of the datagridview.
You requirement sounds somewhat odd. Your comment ”I wish to hide or set visibility to false of the bottom row that partially visible in dgv that is docked to fill.”... I am curious how you would know this is the last row? Is it not possible that there are more rows below the last one visible? If the scroll bars are available you should see the vertical one if rows go beyond its bounding box. If one of the rows is cut in half by the bounding box and there is more than 1 row below this row, then making invisible/hiding/deleting that row will simply move the next one up.
Since the DataGridView is docked you may have to resize the rows manually if you do not want the rows to be split by the bounding box. Another possible solution is to use the DataGridViews AutoSizeRowsMode Like below.
dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells;
This will set the rows so that a row will not be chopped if it is outside the bottom of the bounding box. The rows will auto size to fit evenly There are seven (7) AutoSizeRowsMode options and I am guessing one of them may do what you are looking for. I am guessing DisplayedCells may work for what you describe. If the grid is re-sized often, you may have to implement this row resizing. Hope this helps.

changing the position of textbox using code

In my form I have an AXVS Flex Grid and a Textbox. Firstly the textbox will not be visible.
When the focus is on a particular column of the flexgrid, the textbox will be visible and the Flex Grid will be disabled. The position of the text box will be at the bottom of the particular row at the first time.
But when another row is inserted, then I need to change the position of the textbox to the bottom of the new row and so on.
How can I do that? Thanks in advance.
Position of a control can be retrieved and set using the Top & Left properties of the control.
So you can get the Top,Left property of the inserted row and set the Top,Left property of TextBox accrodingly.
e.g.
TextBox1.Top = InsertedRow.Top +=10
TextBox1.Left = InsertedRow.Left
This will bring the textbox below inserted row.