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

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!

Related

Datagridview.Rows(#).Selected not updating CurrentRow.Index

VB.Net 4.6.1
Windows Forms application
I have a bound datagridview that I'm trying to sort and select. The data loads fine and I can click the headers (with some code) and the sorting works well. I'm working on reselecting a record after the sort is complete and I'm running into some trouble.
Assume that I have a datagridview with 20 records in it. On the form I also have a button that runs the following:
MessageBox.Show(MyDataGridView.CurrentRow.Index.ToString)
I also have a Sub that handles MyDataGridView.Sorted and in it I have one test line as follows:
MyDataGridView.Rows(2).Selected = True
After the data loads I click on the 11th record (selectionmode fullrowselect) and then I click the button. Box pops up and says "10" (0 based index). I click one of my column headers, the data sorts and the highlight bar jumps up to the 3rd record (index 2). However when I hit my currentrow.index button it still says 10. Additionally if I hit the down arrow key the selection bar jumps down to the 11th (index 10) record in the list.
It seems that using "Selected" doesn't update the currentrow.index value and since it is read-only I can't force it. Can anyone educate me on what's going on because, as it is, my users would be confused if the arrow up and down keys didn't work properly after a sort.
Thank you!
"Current" and "selected" do not mean the same thing. How could they, when multiple rows can be selected but there can only be one current row? The current row is the row that currently contains the caret and a selected row is one that is highlighted. If you want the row at index 2 to be the current row then you need to make a cell in that row the current cell, i.e. assign a cell in that row to the CurrentCell property.

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.

Inconsistent TableLayoutPanel resize behaviur

I have two TableLayout Panels, placed one above the other on a form. They each have the same number of columns (created at runtime) that line up with each other. They are not docked, both are anchored in a parent TLP.
When I resize the form, most of the time both TLPs resize together and line up exactly. If I resize several times (usually between 5 and 10), the TLPs resize out of sync and the columns no longer line up. If I resize again, the problem usually goes away.
The Layout_Dates contains no controls, it is painted instead. The Layout_Calendar is painted and may contain a number of controls, added at runtime. The CellPaint events complete without error.
The TLPs are populated with columns like this:
Layout_Calendar.ColumnStyles.Clear()
Layout_Dates.Width = Layout_Calendar.Width
Layout_Dates.ColumnStyles.Clear()
For i = 0 To MyColumnCount - 1
Layout_Calendar.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, DayPercent))
Layout_Dates.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, DayPercent))
Next
' make last column autosize
Layout_Calendar.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.AutoSize))
Layout_Dates.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.AutoSize))
Layout_Calendar.ColumnCount = Layout_Calendar.ColumnStyles.Count
Layout_Dates.ColumnCount = Layout_Dates.ColumnStyles.Count
I have two because one scrolls vertically and the other doesn't.
I have 'try catch' statements around my cellpaint events for both panels neither of which fire an exception.
I have tried checking the column widths at runtime, but these are in % and do not change.
I've put this in the form resize event:
Layout_Dates.PerformLayout()
Layout_Calendar.PerformLayout()
Does anyone know how to:
a) prevent this happening?
b) identify programmatically that this has happened at runtime?
c) deal with it when it does?

Edit datagrid without clicking

I have a UltraGridWinGrid and I need to naviguate through it without using the mouse.
I can get to the grid with Tabs.
I can give focus to any rows with Tabs and Arrow Keys.
Once I highlight a row, how can I select a specific cell to edit it's content ? (All my cells are editable)
If you can modify the code that is executed when the TAB key is pressed, you can do manually select the next cell and start editing like this :
DataGridView.CurrentCell = theNextCell;
DataGridView.BeginEdit(true)
You still need to calculate which cell is next. This should be easy, increment the column index when you press tab, however if you reached the last column, just change row and set index to 0.
For the arrow keys, you could increment/decrement column or row index, depending of the arrow, and apply the same code as above.

How do I link and excel slicer to an excel slider (scroll bar)?

Excel 2010 have a PivotTable feature called a slicer. Slicers are nice. However, when your slicing on a column with tons of unique values, slicers suck.
I want to know how to tie a slicer to a "slider" (scroll bar), that way I can link a Macro to the Scroll bar that selects all Slicer values less than or equal to the value on the scroll bar. When I change the scroll bar by clicking, the value changes and thus the selected values of the slicer change.
Found a way to do this and avoid the middle man (the slicer). This may have to do with how my own particular data is structured, but I think it will work in general.
Using the Macro Recorder, record yourself setting a value filter on the column you want to have a slicer on. In my case the column is % of Sales with Vendor
We use Value Filters -> Greater Than. Select the column, then input the value. Your pivot table will change. Stop the Macro Recorder.
We need another piece of code. Record a new Macro. With this Macro, clear the filter you just set on the pivot table, then stop the Recorder.
Developer -> Insert -> Scroll Bar. Just put the scroll bar anywhere for now.
Enter a value in the range of values of % of Sales with Vendor into a cell like A1. While my pivot table shows the data as a percentage, the underlying source uses decimals. For 20%, I will enter 2. Why? You CANNOT scroll bar on non-integer values. I really want 0.2 but by entering =A1/10 in an adjacent cell, I can always reference the value I really want
You need to create one macro only (from the two you recorded) that looks like this.
Sub sliderfilter()
'
' sliderfilter Macro
'
'
ActiveSheet.PivotTables("PivotTable2").PivotFields("Vendor"). _
ClearAllFilters
ActiveSheet.PivotTables("PivotTable2").PivotFields("Vendor").PivotFilters. _
Add Type:=xlValueIsGreaterThan, DataField:=ActiveSheet.PivotTables( _
"PivotTable2").PivotFields("% of Sales with Vendor"), Value1:=Range("B1").Value
End Sub
A1 is where you had the value 2. The Scroll bar should have Cell Link $A$1. However, you Macro reference B1... the place where you divide by ten to be in the proper range of the % of Sales with Vendor values.
Of course, you assign the macro to the Scroll bar.
When you change the scroll bar, it changes A1, and B1, and tells the Macro to execute a Value Filter, using the value in B1. You have thus created a SLIDER, because no you can just click or slide through the scroll bar values (PS. A scroll bar with the long edge horizontal, is a slider)