What I want to do is to enable a user to delete the last row of data within a specific table. When the user does so, if they click the command button again, then the next row of data above is also deleted and so forth until this process stops at the header.
So in the image shown there are currently, 6 lines of data - the last row having numbers 160, 170 and 180 in the cells [P22, Q22 and R22 respectively]. When the user clicks the command button, these figures will be deleted. If the user then clicks the command button again then the next row of numbers above, being 130, 140 and 150 [P21, Q21 and R21 respectively] will be removed and so forth.
If say there are initially only 3 lines of data showing on the form,and the user clicks the command button, then the last figures in the row, 70, 80 and 90 [P19, Q19 and R19] would be deleted. If the command button is clicked again, then the figures in the row above, 40, 50 and 60 [P18, Q18 and R18] are deleted - process continues until stopping at the headers.
enter image description here
Any help would be appreciated, thanks
Assuming your "table" is an Excel table (and not just a range formatted to resemble a table), the code below should work.
My code assumes you have a table called "Table1" on a worksheet called "Sheet1". Change as appropriate for you.
Option Explicit
Private Sub DeleteLastRowInTable()
With ThisWorkbook.Worksheets("Sheet1").ListObjects("Table1")
If .ListRows.Count > 0 Then
.DataBodyRange.Rows(.DataBodyRange.Rows.Count).EntireRow.Delete
End If
End With
End Sub
The If statement is meant to prevent errors when the table has no data (beneath its headers).
Related
I am doing a simple VBA script in Microsoft Excel which iterates a list of cars and a list of information about when the cars were refueled to provide an overview of how many kilometers each car is driving each month.
I make use of the Range.End property to calculate the number of rows with data and then loop through the indicies.
Set Data = Worksheets("Tankninger") ' Danish for refuellings
NumRows = Data.Range("A1", Data.Range("A1").End(xlDown)).Rows.Count
For x = 1 To NumRows
' Process data
Next
Everything seemed to be working fine, however I found that if someone applied a filter to e.g. the sheet with refuelling data - e.g. only showing data related to car A, then NumRows would be assigned the index of the last visible row.
Example: if the refuling sheet contains 100 records and the records related car A are located on row 50-60, then NumRows would be assigned the value 60 - resulting in my script ignoring the last 40 records.
Is there a way to make the Range.End property ignore any filter applied to sheet, or will I have to change the implementation to use a while-loop instead?
I ended up replacing the for-loop with a while-loop. This allowed me to access every cell regardless of any filtering applied to the sheets.
Set Data = Worksheets("Tankninger") ' Danish for refuellings
r = 2
While Not IsEmpty(Cars.Cells(r, 1).value)
' Process data
Wend
What you can do is add the following in your code to remove filters before you find the last row with data.
'Remove all filters
Worksheets("Sheet1").Activate
On Error Resume Next
ActiveSheet.ShowAllData
I have a userform in Excel. On loading, the form pulls data from the last row of a spreadsheet. There is a button on the form to print the form.
Prior to printing the form, it updates the selection in a list box for work order status to "Assigned" and then copies this status to the spreadsheet.
Sometimes the work order status in the spreadsheet is updated to "". It is like the selection of the list box is not being recognized. It is intermittent and I have not been able to determine a pattern.
This is the code
PrintWOForm.LB_WOStatus.value = "Assigned" 'Updates WO status to Assigned
To write this to the spreadsheet I have this code
'Update WO Status to Complete if there is a date in Date Completed
'Else update Status based on Selection in WO Status list box
If PrintWOForm.TB_DateComplete = "" Then
ws.Cells(cRow, 4) = PrintWOForm.LB_WOStatus.value
Else
ws.Cells(cRow, 4) = "Complete"
ws.Cells(cRow, 23) = PrintWOForm.LB_RepairCode.value
End If
It appears when I first open the form and use the print button, which updates the selection in the list box LB_WOStatus to "Assigned", it copies a blank into cRow 4.
If I manually select a status in the list box, that time and every time forward it will work correctly even when the status is selected by the code.
I am not sure this is best the fix for my issue, but so far it appears to work well. I added the below first line of code in front the prexesting second line of code.
Me.LB_WOStatus.SetFocus 'Must SetFocus to the WOStatus list box for the application to realize the next line of code
Me.LB_WOStatus.value = "Assigned" 'Updates WO status to Assigned
I did not try using the SetFocus method previously because I read on one of these websites that this was only used to set the focus to the object for the user of the form.
I'm trying to create a monthly report for my company and I'm having troubles with the aesthetics of it. I have tables (with lots more data) that looks like this:
enter image description here
textwise looks like this (if picture is unavailable)
Customer 1 - 2018-###-#33
Customer 2 - 2017-###-###
----------------2018-###-###
Customer 3- 2018-###-###
etc
but sometimes there is a page break in the middle of a customer data, so that the title shows up on the first page but the last row(s) are on a new page.
I am trying to come up with a code to sense whether or not the data range will be split up, but I can not. I had thought maybe the pagebreak could be anticipated with the row number (as that's how I'm grouping the data) but one sheet has the break on row 101 (because this data starts at row 46) and the other has the pagebreak on row 106.
I have tried doing something similar to this:
If i >= 102 And start.row <= 101 Then
Worksheets(storenumber).HPageBreaks.Add before:=Rows(start.row)
Else
If i >= 176 And start.row <= 166 Then
Worksheets(storenumber).HPageBreaks.Add before:=Rows(start.row)
End If
End If
(with varying i = numbers and combination) but I haven't had any success.
Does anyone else have any other ideas? there normally is only one page break per storenumber sheet, with the except of one sheet. (and some sheets don't need a page break as they only have say 5 customers)
I'm looking for an easier code (excel beginner/intermediate) but I'm open to any ideas. Thanks for your help!
This code seems to work for me:
Option Explicit
Sub BreakPagesCleanly()
Dim pb As HPageBreak
Dim rng As Range
Dim i As Long
ActiveWindow.View = xlPageBreakPreview
ActiveSheet.ResetAllPageBreaks
For Each pb In ActiveSheet.HPageBreaks
If pb.Location.Value = "" Then
'go back to the last value
Set rng = pb.Location.End(xlUp)
ActiveSheet.HPageBreaks.Add before:=rng
DoEvents 'Seems to be required to give Excel time to catch up
End If
Next pb
End Sub
Here's the before view, vs the after:
I am new to programming and I want to create an application for basketball coaches to be able to keep stats of their players by using VBA in Excel with command buttons.
Instead of manually inputting stats for each player in a game, I want to be able to click a command button with a players name on it to select that player's row. Then click a button that will have an action on it and input a number.
I will have 12 buttons for the players and 40 buttons for the actions (e.g. pts, reb,stl,etc.)
For example: When I click the player's name button, it will select the row that the player's attribute are in. Then when I select the action (e.g. points), it will add the number 2 to the column labeled points.
I want to use the action buttons for all 12 players so only put the number in when i click the player's name button. So the "pts" button will work for all 12 player buttons. Overall, I want to make a stat sheet for the coaches with command buttons instead of moving the cursor and inputting the information in manually.
Any suggestions on how to do so? Thank you in advance.
Clancy
Some example code, using a module-scoped variable to store which player is being processed, might be:
Option Explicit
Private CurrentPlayerRow As Long
Sub PlayerA_Click()
CurrentPlayerRow = 3
End Sub
Sub PlayerB_Click()
CurrentPlayerRow = 4
End Sub
Sub PlayerC_Click()
CurrentPlayerRow = 5
End Sub
Sub Action1_Click()
'Update column D by adding 2 to the cell value
Cells(CurrentPlayerRow, "D").Value = Cells(CurrentPlayerRow, "D").Value + 2
End Sub
Sub Action2_Click()
'Update column G by adding an inputted number to the cell value
Cells(CurrentPlayerRow, "G").Value = Cells(CurrentPlayerRow, "G").Value + CLng(InputBox("Enter a number:"))
End Sub
(Not knowing anything about basketball scoring and/or statistics, I wasn't sure what sort of actions you wanted to process.)
I have a 2200+ page text file. It is delivered from a customer through a data exchange to us with asterisks to separate values and tildes (~) to denote the end of a row. The file is sent to me as a text file in Word. Most rows are split in two (1 row covers a full line and part of a second line). I transfer segments (10 page chunks) of it at a time into Excel where, unfortunately, any zeroes that occur at the end of a row get discarded in the "text to columns" procedure. So, I eyeball every "long" row to insure that zeroes were not lost and manually re-enter any that were.
Here is a small bit of sample data:
SDQ EA 92 1551 378 1601 151 1603 157 1604 83
The "SDQ, EA, and 92" are irrelevant (artifacts of data transmission). I want to use Excel and/or VBA to select 1551, 1601, 1603, and 1604 (these are store numbers) so that I can copy those values, and transpose paste them vertically. I will then go back and copy 378, 151, 157, and 83 (sales values) so that I can transpose paste them next to the store numbers. The next two rows of data contain the same store numbers but give the corresponding dollar values. I will only need to copy the dollar values so they can be transpose pasted vertically next to unit values (e.g. 378, 151, 157, and 83).
Just being able to put my cursor on the first cell of interest in the row and run a macro to copy every other cell would speed up my work tremendously. I have tried using ActiveCell and Offset references to select a range to copy, but have not been successful. Does any have any suggestions for me? Thanks in advance for the help.
It's hard to give a complete answer without more information about the file.
I think if your input data is 2200+ pages long, it's unlikely that opening it with the default excel opening functions is the way to go. Especially since Excel has maximum number of rows and columns. If the file is a text file (.txt) I would suggest opening it with VBA and reading each line, one at a time, and processing the data.
Here's an example to get you started. Just keep in mind that this is transposing each row of text into columns of data, so you will quickly fill all the columns of excel long before you run thru 2200 pages of text. But it's just an example.
Sub getData()
dFile = FreeFile
sFile = "c:\code\test.txt"
Open sFile For Input As #dFile
c = 1
'keep doing this until end of file
Do While Not EOF(dFile)
'read line into dataLine
Input #dFile, dataLine
' break up line into words based on spaces
j = Split(dataLine, " ")
jLength = UBound(j)
If jLength > 2 Then
r = 1
'ignore first 3 words
'and get every other word
'transpose rows of text into columns
For word = 3 To jLength Step 2
Cells(r, c) = j(word)
r = r + 1
Next word
End If
c = c + 1
Loop
Close #Data
End Sub