I'm trying to make a checkbook register on excel 365. I am trying to add the feature of deleting a row(transaction) but when I run my vba code it errors out with the following: Run-time error '1004': Paste method of worksheet class failed.
When I run my code to delete a row the balance column fills up with "#REF". My effort to fix this by copying the balance column and pasting it back after the row is deleted isn't working. Balance column still fills up with "#REF"s. Here is the code i'm using to copy and paste the balance column:
Sub DeleteTransactionRectangle_Click()
Dim deletedRow
Dim rng As Range
Set rng = Selection
deletedRow = rng.Row
MsgBox (deletedRow)
Worksheets("Register").Range("I:I").Copy
rng.EntireRow.Delete
ActiveSheet.Paste Destination:=Worksheets("Register").Range("I:I")
End Sub
Anyone have any ideas to make this work.
You have dim 'rngg' but set 'rng' - should these not both be the same?
When you delete the row, it seems the copied information is lost from the clipboard. Instead, you could copy the formula from column I in the preceding row, and paste it back into the row you deleted:
rng.EntireRow.Delete
ActiveSheet.Range("I" & deletedRow - 1).Copy
ActiveSheet.Range("I" & deletedRow).Select
ActiveSheet.Paste
Deleting Rows Containing Formulas
Tip
In design mode, right-click on the command button and select Properties. Change TakeFocusOnClick to False, so when you click the command button it doesn't get selected (focus) but the selection on your sheet stays the same.
Formula
Your formula turns out to be bad when deleting rows. You could change it to:
=SUM(H$1:H2)-SUM(F$1:F2)
which is 'deleting columns proof'.
Improve Code
To Study
Range.Find
method
Areas object
Range.Areas property
Range.Resize property
Application.Union method
Application.Intersect method
Change the values in the constants section to fit your needs.
Option Explicit
Sub DeleteTransactionRectangle_Click()
Const rowFR As Long = 2 ' First Row of Data
Const colFR As Long = 9 ' Formula Column
Dim rowLR As Long ' Last Row of Data
Dim rng As Range ' Current Area (For Each Control Variable)
Dim rngTransAction As Range ' Transaction (Column) Range
Dim rngUnion As Range ' Union Range
Dim rngFinal As Range ' Intersection (Final) Range
' Calculate Last Row of Data.
rowLR = Columns(colFR).Find(What:="*", LookIn:=xlFormulas, _
SearchDirection:=xlPrevious).Row
' From the selection, create Union Range which only contains cells
' of Formula Column, which will later be compared
' to Transaction (Column) Range.
For Each rng In Selection.Areas
If Not rngUnion Is Nothing Then
Set rngUnion = Union(rngUnion, Cells(rng.Row, colFR) _
.Resize(rng.Rows.Count))
Else
Set rngUnion = Cells(rng.Row, colFR).Resize(rng.Rows.Count)
End If
Next
' Define Transaction (Column) Range.
Set rngTransAction = Cells(rowFR, colFR).Resize(rowLR - rowFR + 1)
' Create Intersection (Final) Range which will 'eliminate'
' all 'non-valid' areas of the Selection Range. 'Non-valid' areas are
' the ones before First Row of Data and after Last Row of Data.
If Not rngUnion Is Nothing Then Set rngFinal _
= Intersect(rngUnion, rngTransAction)
' Delete rows of Intersection (Final) Range.
If Not rngFinal Is Nothing Then rngFinal.EntireRow.Delete
End Sub
Related
I'm working with a Pivot Table and i want to hide all rows in the Grand Total column that show a total of between -1 and 1. In VBA i can hide all of those rows and it works as intended if i specify the exact range e.g ("J5:J100"), however the number of columns will change throughout the month so i need the range to be dynamic.
I'm hoping this is something really simple that I'm missing but i just can't see it.
The code in theory will locate and select the last column, make that selection a range, loop through the range hiding all rows that are of minimal value.
Any ideas?
Current code:
Sub Hide_Rows()
'
' HideRows Macro
'
' Selects Last Column of Pivot Table
With ActiveSheet.PivotTables(1).TableRange1
.Offset(1, .Columns.Count - 1).Resize(.Rows.Count - 1, 1).Select
End With
' Set variables
Dim selection As Range
Dim Cell As Range
Dim rng As Range
' Make the selection a range to run the loop through
Set rng = selection
' Loop to hide all cells between -1 & 1
For Each Cell In rng `(THIS IS WHERE THE CODE STOPS)`
If Cell.Value < 1 And Cell.Value > -1 Then
Cell.EntireRow.Hidden = True
End If
Next Cell
End Sub
I'm using excel vba to delete filtered rows. The code is working just when I specified the range to be on A1 and put my table headers on A1. But, my table headers on B9 so I need to put it on the range but that error occurs. I didn't know why its working for Range("A1") and it didn't work for Range("B9"). In addition when I put A1 as my range to my table it deleted all the rows not just the filtered rows.
Sub Delete_CD_Blanks()
Dim Rng As Range
Dim Rng_Del As Range
Set Rng = Range("B9").CurrentRegion
If Sheets("tt").AutoFilterMode = True Then
Sheets("tt").AutoFilter.ShowAllData
End If
' Rng.AutoFilter field:=4, Criteria1:=” = ”
Rng.AutoFilter field:=6, Criteria1:="??? ?????"
Rng.Offset(1, 0).SpecialCells(xlCellTypeVisible).EntireRow.Delete
Sheets("tt").AutoFilterMode = False
End Sub
You did not ask my clarification questions and I (only) suppose that your problem stays in the fact that there are some cells above the 9th row, which make part from the CurrentRegion. If I am right, please add a code line, able to create a range starting from 9th row (inclusive):
'your existing code
Set rng = Range("B9").CurrentRegion 'existing in your code
Set rng = Intersect(rng, ActiveSheet.rows("9:" & rng.rows.count)) 'it creates a range slice, starting from 9th row and ending to the `CurrentRegion` last row
'your existing code
I'm trying to copy the one specific column(excluding the header) after filtering my dataset. If there are multiple rows after filtering, my selection of range works fine and I am able to copy that column into another sheet. However, if there is only one row after filtering, when I specify the range, it selects all the empty cells along with the non-empty cell and my code is malfunctioning. How do I fix this issue?
I have tried using different range properties but couldn't get the desired outcome
'''Finding the Pack Test Category from the filtered 1st column'''
Set RngA = ActiveSheet.AutoFilter.Range.SpecialCells(xlCellTypeVisible).Areas(2)(1, 1)
''Here the selection of range includes all the empty cells as well!
Set RngA = Range(RngA, RngA.End(xlDown))
'''Copy & Pasting in the Forecast Sheet for temporary use'''
RngA.SpecialCells(xlCellTypeVisible).Copy Destination:=wbA.ActiveSheet.Range("L1")
I expect the range to be selected with only the visible cells having data not the empty cells.
Say we start with:
and filter for age above 45:
we want to copy filtered column A to another sheet:
Sub KopyOneKolumn()
Dim r1 As Range
Dim r2 As Range
Dim r3 As Range
Set r1 = ActiveSheet.AutoFilter.Range ' the total visible range
Set r2 = Intersect(r1.Offset(1, 0), r1) ' clip off the header
Set r3 = Intersect(r2, Columns(1)) ' pick only column A
r3.Copy
Sheets("Sheet2").Paste
End Sub
Result in Sheet2:
NOTE:
The key point is that r1 represents a "copy-able" block of visible cells in the autofilter table.
Relying on Areas(2) is not going to work if the first row under the header is part of the filtered (visible) cells.
'at this point, AutoFilter has been applied
'I have no idea what the range is
'or what column you are interested in
with ActiveSheet.AutoFilter.Range
with .cells.resize(.rows.count-1, 1).offset(1, 0)
set RngA = .SpecialCells(xlCellTypeVisible)
end with
end with
RngA.copy Destination:=wbA.ActiveSheet.Range("L1")
I disagree with your use of ActiveSheet as the parent worksheet references. The source and destination worksheets should be explicitly referenced.
Excel as database with images in column:
I would like to make a tool which allows in one sheet the selection of products, all the necessary discount calculations and then print the selection as a quotation for a customer.
The table is filtered and then the visible rows copied to another table ready for printing.
One of the columns contains images. Images are wisely attached to the cells ("move but NOT size with cells")
if I filter them, images failed to be filtered, they get superimposed.
if after filtering I would like to copy them to another table, formatted for printing. They land in accidental locations, not in cell positions where I would like them to land.
Is there a solution to copy and paste images in excel exactly as they are, without changing location and size (attached to destination Cells with VBA?
===
What i tried:
The user filters records in a table s/he would like to include in a quotation.
By pressing a button s/he runs a macro. It first cleans all drawings and data in target table to which the records will be copied. Then text is copied separately and images separately to their destination columns with the code:
With Sheets ("QuotationPrint")
'copy descriptions
Sheets("oferta stal").ListObjects("tblPricelist").ListColumns("Descriptions").DataBodyRange.SpecialCells(xlCellTypeVisible).Copy
.Range("c8").PasteSpecial Paste:=xlPasteAllUsingSourceTheme ', SkipBlanks:=True
'copy images
Sheets("oferta stal").ListObjects("tblPricelist").ListColumns("images").DataBodyRange.SpecialCells(xlCellTypeVisible).Copy
.Range("o8").Select
ActiveSheet.Paste
.Columns("H:I").Hidden = True
.Range("n8:n300").SpecialCells(xlCellTypeBlanks).EntireRow.Hidden = True
.Range("c8:c300").SpecialCells(xlCellTypeVisible).EntireRow.AutoFit
End With
Here my skills end. What to do to avoid distortion of copied images?
EDIT:
Example data would contain here two columns (for simplifiaction purposes)
1 Table name (listobject.table or data table created with Ctrl+t)
is 'tblPriceList.
Descriptions | images
------------------------
Lorem ipsum..| image1
Lorem muspi..| image2
meroL ipsum..| image3
Images are pasted and then they are attached to cell with option "Move but not resize with cell" The user uses filter to select, say row 1 and row 3. then the macro copies selected cells to new empty range starting with (O,8) in antother sheet. After data is pasted cells height are adjusted.
Here is reproducible example excel file showing the problem. Data is first filtered by user. Images fail to get filtered and get copied incorrectly: https://drive.google.com/open?id=1bGXuB47dFqhp9wsYcuBTB7Se6gelPnok
OK, I got something working here:
The CopyVisible function loops through the listobject and checks if the the row is visible, if that is the case the description and all pictures intersecting with the cell. This occures in the right format if one copies more than one cell with a picture in it this gets messed up for a to me unknown reason.
Option Explicit ' use this
Public Sub CopyVisible()
Dim SSheet As Worksheet ' Source
Dim TSheet As Worksheet ' Target
Dim Scell As Range ' Target
Dim Tcell As Range 'Source
Dim Tbl As ListObject
Dim offset As Integer
Dim Pic As Shape
Dim Picrng As Range
Set TSheet = Worksheets("QuotationPrint")
Set SSheet = Worksheets("oferta stal")
Set Tbl = SSheet.ListObjects(1)
TSheet.Range("b8:o300").ClearContents 'remove everything below row 8
'Call DeletePicAll
Set Tcell = TSheet.Range("c8")
offset = 10 ' "from c8 to o8 the offset is 10
For Each Scell In Tbl.ListColumns(1).DataBodyRange ' loop through table
If IsVisible(Scell)(1, 1) Then ' only copy if visible
'description
Scell.Copy
Tcell.PasteSpecial Paste:=xlPasteAllUsingSourceTheme ', SkipBlanks:=True
Tcell.EntireRow.AutoFit
'image
For Each Pic In SSheet.Shapes
Set Picrng = Range(Pic.TopLeftCell.Address & ":" & Pic.BottomRightCell.Address)
If Not Intersect(Picrng, Scell.offset(0, 1)) Is Nothing Then
Pic.Copy
Tcell.offset(0, offset).PasteSpecial
End If
Next
Set Tcell = Tcell.offset(1, 0)
End If
Next Scell
End Sub
This function was copied from Cpearson and helps determine if a cell is visible or not. It can also be used for a range.
Public Function IsVisible(InRange As Range) As Boolean()
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' IsVisible
' This function returns an array of Boolean values indicating whether the
' corresponding cell in InRange is visible.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Dim R As Range
Dim Arr() As Boolean
Dim RNdx As Integer
Dim CNdx As Integer
ReDim Arr(1 To InRange.Rows.Count, 1 To InRange.Columns.Count)
For RNdx = 1 To InRange.Rows.Count
For CNdx = 1 To InRange.Columns.Count
Set R = InRange(RNdx, CNdx)
If R.EntireRow.Hidden = True Or R.EntireColumn.Hidden = True Then
Arr(RNdx, CNdx) = False
Else
Arr(RNdx, CNdx) = True
End If
Next CNdx
Next RNdx
IsVisible = Arr
End Function
All in all the problem should be solved with it. A few tips at the end: Declare your variables and force yourself to do it using the Option Explicit try not to use select and activate and if you use listobjects utilize the ability to loop through listrows, listcolumns or the databodyrange.
In reference to: Copy a row in excel if it matches a specific criteria into a new worksheet
I attempted applying the above hyperlink code to the needs of my own workbook. The only notable differences are: Object names, My data begins in "A2" instead of "A1", and my data is being copied to "L" column in a new worksheet instead of "A" column
Also... you can assume I have generated tabs in excel that correspond with each SelectCell.Value.
Sub Consolidate_Sheets()
Dim MyCell As Range
Dim MyRange As Range
Dim ws As Worksheet
Set MyRange = Sheets("Install_Input").Range("A2")
Set MyRange = Range(MyRange, MyRange.End(xlDown))
Call superSizeMe(MyCell, MyRange)
Sub superSizeMe(SelectCell As Range, SelectRange As Range)
Dim InstallInput As Worksheet
Dim strPasteToSheet As String
'New worksheet to paste into
Dim DestinationSheet As Worksheet
Dim DestinationRow As Range
'Define worksheet with input data
Set InstallInput = ThisWorkbook.Worksheets("Install_Input")
For Each SelectCell In SelectRange.Cells
InstallInput.Select
If SelectCell.Value <> "" Then
SelectCell.EntrieRow.Select ''''LOCATION OF RUN-TIME ERROR 438''''
Selection.Copy
Set DestinationSheet = Worksheets(SelectCell.Value)
Set DestinationRow = DestinationSheet.Range("L1:L" & DestinationSheet.Cells(Rows.Count, "L").End(xlUp).Row)
Range("L" & DestinationRow.Rows.Count + 1).Select
ActiveSheet.Paste
End If
Next SelectCell
InstallInput.Select
InstallInput.Cells(1, 1).Select
If IsObject(InstallInput) Then Set InstallInput = Nothing
If IsObject(SelectRange) Then Set SelectRange = Nothing
If IsObject(SelectCell) Then Set SelectCell = Nothing
If IsObject(DestinationSheet) Then Set DestinationSheet = Nothing
If IsObject(DestinationRow) Then Set DestinationRow = Nothing
End Sub
I am getting a Run-time error'438'
"Object doesn't support this property or method" on "SelectCell.EntireRow.Select"
Well your code has a typo
SelectCell.EntrieRow.Select
should say entire not Entrie. Personally I would use this method anyway, It selects the entire row based on the number you put in. FYI there is also a corresponding Columns().select if you need it in the future
sel_cell_row = SelectCell.Row
Rows(sel_cell_row).select
edit addressed to comment
The reason you get the 1004 error is like it says, the copy and paste areas don't match. Think of copying 10 rows, and trying to paste it into 2 rows, simply wouldn'y work. I'm guessing the problem actually stems from your destinationrows code. I'm not entirely sure what its trying to do, but here are two generic fixes
1)keep the copy code as it is, and modify the paste. Instead of selecting a range of cells to paste into, select the first cell (if your range was a1:a10, selecting a1 is sufficient) excel will then paste all the data starting at that first cell. so in your code do this
'comment out all this destination row stuff
'Set DestinationRow = DestinationSheet.Range("L1:L" & DestinationSheet.Cells(Rows.Count, "L").End(xlUp).Row)
'Range("L" & DestinationRow.Rows.Count + 1).Select
Range("L1").select 'only referencing the first cell to paste into
ActiveSheet.Paste
2)rather than selecting an entire row, why not select only the populated values in that row something like
sel_cell_row = SelectCell.Row
lastColumn = ActiveSheet.Cells(2, Columns.Count).End(xlToLeft).Column
range(Cells(sel_cell_row ,1),Cells(sel_cell_row ,lastColumn )).select
then do your copy as usual. the 1 is for column 1, or A. I'm assuming the data you want is in one row starting at column A and going till lastColumn. Maybe now this will match your destinationrows code.
3)Com,bine options 1 and 2. so copy only the populated cells, and paste to the first cell in the range