When creating a blank Excel Workbook, the file size is kept small by not using all 1,000,000+ rows. However, once data has been added to all of the rows, the rows still exist even if the data is deleted out of them, resulting in a huge filesize. I know these rows still exist because of the size of the scrollbar and the fact that if I scroll to the bottom I end up at row 1,000,000+ which does not happen on a new Workbook. I guess this would be called the UsedRange in VBA?
I have inherited a Workbook from another developer which is in this situation and I'm looking for a way to reduce the size. I can copy the used data only into a new blank Workbook, but does anyone know of a way to reduce the actual UsedRange?
The following code does not work:
Sub test()
Dim r As Range
Set r = Range("10000:1000000")
r.Delete
End Sub
Nor does highlighting the rows manually, clicking in the header and clicking delete
Open VBA and type ActiveSheet.UsedRange in the immediate window.
I added it to my right-click menu since I use it so often.
Edit:
Here's the code I use to add it to the context menu:
Private Sub Auto_Open()
On Error Resume Next
'delete the control if it exists
Application.CommandBars.FindControl(Tag:="MY_TAG").Delete
On Error GoTo 0
With Application.CommandBars("Cell").Controls
'add reset range button
With .Add(Type:=msoControlButton)
.Caption = "Reset used range"
.OnAction = ThisWorkbook.Name & "!ResetRange"
.Tag = "MY_TAG"
.BeginGroup = True
End With
End With
End Sub
Private Sub ResetRange()
ActiveSheet.UsedRange
End Sub
To clear all unused rows and columns in all sheets :
Sub ReduceFileSize()
Dim wB As Workbook
Dim wS As Worksheet
Set wB = ThisWorkbook
For Each wS In wB.Sheets
DeleteUnUsed wS
Next wS
wB.Save
End Sub
Sub DeleteUnUsed(wS As Worksheet)
Dim r As Range
Dim LastRow As Double
LastRow = LastRow_1(wS)
Dim LastCol As Double
LastCol = LastCol_1(wS)
With wS
.Range(LastRow + 1 & ":" & .Rows.Count).EntireRow.Delete
.Range(collet(LastCol) & ":" & collet(.Columns.Count)).EntireColumn.Delete
End With
End Sub
Public Function LastRow_1(wS As Worksheet) As Double
With wS
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
LastRow_1 = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Else
LastRow_1 = 1
End If
End With
End Function
Public Function LastCol_1(wS As Worksheet) As Double
With wS
If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
LastCol_1 = .Cells.Find(What:="*", _
After:=.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
Else
LastCol_1 = 1
End If
End With
End Function
Public Function ColLet(x As Integer) As String
With ActiveSheet.Columns(x)
ColLet = Left(.Address(False, False), InStr(.Address(False, False), ":") - 1)
End With
End Function
Related
Private Sub Updateform()
Dim WB As Workbook
Dim URL As Variant
Dim Sh As Worksheet
Dim WB1 As Workbook
Dim i As Integer
Dim LR As Long
Dim stext As String
Dim stext1 As String
Application.DisplayAlerts = False
ThisWorkbook.Activate
Set WB = ThisWorkbook
Application.DisplayAlerts = False
ThisWorkbook.Activate
Set Sh = ThisWorkbook.Sheets("Database")
irow = ThisWorkbook.Sheets("Database").[Counta(Database!A:A)] + 1
With Sh
ThisWorkbook.Sheets("Emailtosend").Range("A1999").Value = FirstForm2.UD1.Value
stext = ThisWorkbook.Sheets("Emailtosend").Range("A1999").Value
End With
ThisWorkbook.Sheets("Database").Select
Range("A1").Select
On Error Resume Next
ActiveCell.Select
Dim UID As String
UID = stext
For i = 2 To irow
If ThisWorkbook.Worksheets("Database").Cells(i, 10).Value = UID Then
Worksheets("Database").Cells(i, 3).Value = FirstForm2.lstprocessingdate.Value 'iam able to update date
Worksheets("Database").Cells(i, 4).Value = FirstForm2.lstprocessed1.Value
Worksheets("Database").Cells(i, 8).Value = FirstForm2.survey1.Value ' this is a combobox though I change new value it is still not getting updated
Worksheets("Database").Cells(i, 6).Value= FirstForm2.lstcomments.Value ' this is comment box still the new comments are not getting updated
End If
Next
Dim ncell As Range
For Each ncell In Sheets("temp").Range("Checkrange")
With Sh
If FirstForm2.Controls(ncell.Value) = "" Then
MsgBox ("Make sure all text boxes have entries")
Exit Sub
Else
End If
End With
Next ncell
URL = "https://audit.global.com/sites/AdminSS/Shared%20Documents/Training%20Materials/SS%20recurring%20request%20Handbooks/Test/Updated%20Quality%20Tracker.xlsx?d=w68cd37bd0505426fb4d6fe38c21e23a8"
Set WB1 = Workbooks.Open(URL)
Application.Visible = False
Debug.Print WB1.FullName
Set WB1 = ActiveWorkbook
WB1.LockServerFile
If Err.Number <> 0 Then
MsgBox "File is already open, request you to wait for 10 minutes!"
GoTo 0
Err.Clear
Else
MsgBox "The form is getting updated"
End If
Dim rng1 As Variant
WB1.Activate
Range("J1").EntireColumn.Select
Selection.Copy
Range("K1").EntireColumn.Select
Selection.PasteSpecial xlPasteValues
Dim stext2 As String
stext2 = ThisWorkbook.Sheets("Emailtosend").Range("A1999").Value
WB.Activate
WB.Sheets("Database").Range("A1").Select
'If WB1.Worksheets("Database1").Cells(i, 10).Value = UID Then
Set rng1 = Cells.Find(What:=stext2, _
After:=ActiveCell, _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
ActiveCell.Select
ActiveCell.entirerow.Select
Selection.Copy ' copying the entirerow and I want to paste this data in sheet from sharepoint
WB1.Activate
WB1.Sheets("Database1").Select
Set rng1 = Cells.Find(What:=stext2, _
After:=ActiveCell, _
LookIn:=xlFormulas, _
LookAt:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
ActiveCell.Select
ActiveCell.entirerow.Select
Selection.PasteSpecial xlPasteValues ' I want to paste here after searching the text value
WB1.Save
WB1.Close ' to close sharepoint excel
msgvalue = MsgBox("The information has been updated", vbOKOnly)
0:
Application.Visible = False
ActiveWorkbook.Save
ActiveWorkbook.Close
Application.Visible = False
End Sub
I want to update existing macro sheet by calling existing details from userform unique ID and then update new details entered in the existing sheet and other tracker in Sharepoint. Please help
Let me know if you have any questions. Not sure what else to add to this question. Initially the code has to modify the existing details and update the new details and then open Sharepoint Excel and check the unique code, either delete the entire row of the unique code or update the new details by overwriting the existing details in Sharepoint Excel
The code below is meant to run when the Workbook is first opened.
Sub Auto_Open()
Dim LastRow As Integer
LastRow = Sheet6.UsedRange.Rows.Count
ActiveWorkbook.RefreshAll
Sheet6.AutoFill Destination:=Range("Y2:Y" & LastRow)
End Sub
It automatically runs a Refresh All to update any queries or formula in the WorkBook and then autofills the list of data in column Y of sheet6 to the last row of data that can be found in the WorkSheet.
When I go to run the code I get a 'Compile Error: Method of data member not found' which highlights.
.Autofill
What I don't understand is that this works perfectly well on an identical spreadsheet, not just this one.
I have also tried the following code which doesn't work on this sheet but does on the other.
Sub Auto_Open()
ActiveWorkbook.RefreshAll
Sheet6.AutoFill_ListSource
End Sub
ListSource is the name of the table in column Y that I am trying to autofill.
Change:
Sheet6.AutoFill Destination:=Range("Y2:Y" & LastRow)
to:
Sheet6.Range("Y2").AutoFill Destination:=Sheet6.Range("Y2:Y" & LastRow)
Note: a "safer" way to get the last row, will be using the Find function:
Dim LastCell As Range
Dim LastRow As Long
With Sheet6
Set LastCell = .Cells.Find(What:="*", After:=.Cells(1), Lookat:=xlPart, LookIn:=xlFormulas, _
searchorder:=xlByRows, searchdirection:=xlPrevious, MatchCase:=False)
If Not LastCell Is Nothing Then
LastRow = LastCell.Row
Else
MsgBox "Error! worksheet is empty", vbCritical
Exit Sub
End If
End With
i tried to use the formula =Today() on the table of my database and when i try to insert a new row the next day, the whole data even the previous dates had been replace with the current day's date. Is there anyway to prevent it ? Or is it possible to use worksheet_change to update the date's column when new row had been inserted and the new role's date column will have the current day date and the following day when i update again it wont be replaced? Please advise thanks
From Determine whether user is adding or deleting rows by breetdj I write this code. Try to put it in the sheet module:
Option Explicit
Private Sub Worksheet_Change(ByVal Target As Range)
Static LR As Long
Dim Table as range
Set Table = Me.ListObjects(1).DataBodyRange
If LR = 0 Then
LR = Table.Rows.Count
Exit Sub
End If
If Table.Rows.Count < LR Or Table.Cells(Table.Rows.Count, 1) <> "" Then Exit Sub
Table.Cells(Table.Rows.Count, 1) = Date
LR = LR + 1
End Sub
Change "ListObjects(1)" with the name of the table, and change the column number with your desired column
ZQ7, this answer is as I mentioned in the comments, finds the =TODAY() formula cell and paste it's values to it's current cell. Then you can add your new row and run the rest of your code..
Option Explicit
Sub prevenddate()
Dim mert As Range
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet1")
Cells.Find(What:="=TODAY()", After:= _
ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Copy
ActiveCell.PasteSpecial xlPasteValues
End Sub
And here is the desired answer!
This below code, firstly looks for any =TODAY() formula in worksheet, and if the result is today's date it doesn't do anything. But if it's different then today's date then it simply does Paste Values
Private Sub Worksheet_Change(ByVal Target As Range)
Dim wb As Workbook
Dim ws As Worksheet
Dim myRw As Long, myCl As Long
Set wb = ThisWorkbook
Set ws = wb.Sheets("Sheet1")
On Error GoTo 10
myRw = ActiveCell.Row
myCl = ActiveCell.Column
ws.Cells.Find(What:="=TODAY()", After:= _
ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False, SearchFormat:=False).Activate
If ActiveCell.Value <> Date Then
Cells.Find(What:="=TODAY()", After:= _
ActiveCell, LookIn:=xlFormulas, LookAt:=xlPart, SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, MatchCase:=False, SearchFormat:=False).Activate
ActiveCell.Copy
ActiveCell.PasteSpecial xlPasteValues
Else
End If
10
ws.Cells(myRw, myCl).Offset(-1, 0).Activate
Application.CutCopyMode = False
End Sub
please try this code
Public Function MyToday() As Date
MyToday = CDate(Now() \ 1)
End Function
and should be called like
MyToday()
Place the following code on Sheet Module.
The code will insert a Date in column A if you input something in column B starting from Row2.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim r As Long
On Error GoTo SkipError
If Target.Column = 2 And Target.Row > 1 Then
Application.EnableEvents = False
r = Target.Row
If Target <> "" Then
If Cells(r, "A") = "" Then
Cells(r, "A") = Date
End If
Else
Cells(r, "A") = ""
End If
End If
SkipError:
Application.EnableEvents = True
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
'Dim Rg As Range
'Dim G As Integer
'Dim varno As Long
With Sheet1
Range("J5:J5").AutoFill Destination:=Range("j5:j218")
'Range("L8").Formula = "=IF(AND(F5="",G5="",H5=""),"",I4+F5-G5-H5)"
'Range("L8").Formula = ""
End With
End Sub
Range("L8").Formula = "=IF(AND(F5="",G5="",H5=""),"",I4+F5-G5-H5)"
i try but it does not appear
I am trying to copy all worksheets, one at a time, and pasting into a new worksheet. These files come from multiple third parties so the worksheets can vary. I'm running into a problem below when trying to determine last row Lrow and last column Lcol because an error appears saying Object doesn't support this property or method. I do plan on submitting this to my work so any help with error proofing or general macro tips are appreciated.
Sub ws_copy()
Dim Lrow As Long
Dim Lcol As Long
Dim Pasterow As Long
Dim WSCount As Integer
Dim i As Integer
'On Error Resume Next
'Application.DisplayAlerts = False
i = Application.InputBox(prompt:="Enter the place order of first tab to be copied.", Title:="Worksheet Consolidation", Type:=1)
If IsEmpty(i) = True Then
Exit Sub
Else
If IsNumeric(i) = False Then
MsgBox "Enter a numeric value."
Else
If IsNumeric(i) = True Then
Worksheets.Add(before:=Sheets(1)).Name = "Upload"
WSCount = Worksheets.Count
For i = i + 1 To WSCount
Lrow = Worksheets(i).Find("*", After:=Cells(1, 1), _
LookIn:=xlFormulas, _
Lookat:=xlPart, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Lcol = Worksheets(i).Find("*", After:=Cells(1, 1), _
LookIn:=xlFormulas, _
Lookat:=xlPart, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
Pasterow = Lrow + 1
Workbook.Worksheets(i).Range(Cells(1, 1), Cells(Lrow, Lcol)).Copy
Workbook.Worksheets("Upload").Cells(Pasterow, 1).Paste
Next i
Else
Exit Sub
End If
End If
End If
'On Error GoTo 0
'Application.DisplayAlerts = False
End Sub
A common way to find the last row/column is:
With Worksheets(i)
Lrow = .Cells(.Rows.Count, 1).End(xlUp).Row
Lcol = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With
hth
Based on the comment that:
I can't assume any one column or row has the last piece of data because of the variety of the files received.
You should look at using the UsedRange property of the Worksheet (MSDN). UsedRange expands as more data is entered onto the worksheet.
Some people will avoid using UsedRange because if some data has been entered, and then deleted then UsedRange will include these 'empty' cells. The UsedRange will update itself when the workbook is saved. However, in your case, it doesn't sound like this is a relevant issue.
An example would be:
Sub Test()
Dim wsSource As Worksheet
Dim wsTarget As Worksheet
Dim rngSource As Range
Dim rngTarget As Range
Set wsSource = ThisWorkbook.Worksheets("Sheet1")
Set wsTarget = ThisWorkbook.Worksheets("Sheet2")
Set rngSource = wsSource.UsedRange
rngSource.Copy Destination:=wsTarget.Cells
End Sub
Here is a method of finding the last used row and last used column in a worksheet. It avoids the issues with UsedRange and also your issues of not knowing which row might have the last column (and which column might have the last row). Adapt to your purposes:
Option Explicit
Sub LastRowCol()
Dim LastRow As Long, LastCol As Long
With Worksheets("sheet1") 'or any sheet
If Application.WorksheetFunction.CountA(.Cells) > 0 Then
LastRow = .Cells.Find(what:="*", after:=[A1], _
LookIn:=xlFormulas, _
searchorder:=xlByRows, _
searchdirection:=xlPrevious).Row
LastCol = .Cells.Find(what:="*", after:=[A1], _
LookIn:=xlFormulas, _
searchorder:=xlByColumns, _
searchdirection:=xlPrevious).Column
Else
LastRow = 1
LastCol = 1
End If
End With
Debug.Print LastRow, LastCol
End Sub
Although the basic technique has been long used, Siddarth Rout, some time ago, posted a version adding COUNTA to account for the case where the worksheet might be empty -- a useful addition.
If you want to merge data on each sheet into one MasterSheet, run the script below.
Sub CopyRangeFromMultiWorksheets()
Dim sh As Worksheet
Dim DestSh As Worksheet
Dim Last As Long
Dim CopyRng As Range
With Application
.ScreenUpdating = False
.EnableEvents = False
End With
'Delete the sheet "RDBMergeSheet" if it exist
Application.DisplayAlerts = False
On Error Resume Next
ActiveWorkbook.Worksheets("RDBMergeSheet").Delete
On Error GoTo 0
Application.DisplayAlerts = True
'Add a worksheet with the name "RDBMergeSheet"
Set DestSh = ActiveWorkbook.Worksheets.Add
DestSh.Name = "RDBMergeSheet"
'loop through all worksheets and copy the data to the DestSh
For Each sh In ActiveWorkbook.Worksheets
If sh.Name <> DestSh.Name Then
'Find the last row with data on the DestSh
Last = LastRow(DestSh)
'Fill in the range that you want to copy
Set CopyRng = sh.Range("A1:G1")
'Test if there enough rows in the DestSh to copy all the data
If Last + CopyRng.Rows.Count > DestSh.Rows.Count Then
MsgBox "There are not enough rows in the Destsh"
GoTo ExitTheSub
End If
'This example copies values/formats, if you only want to copy the
'values or want to copy everything look at the example below this macro
CopyRng.Copy
With DestSh.Cells(Last + 1, "A")
.PasteSpecial xlPasteValues
.PasteSpecial xlPasteFormats
Application.CutCopyMode = False
End With
'Optional: This will copy the sheet name in the H column
DestSh.Cells(Last + 1, "H").Resize(CopyRng.Rows.Count).Value = sh.Name
End If
Next
ExitTheSub:
Application.Goto DestSh.Cells(1)
'AutoFit the column width in the DestSh sheet
DestSh.Columns.AutoFit
With Application
.ScreenUpdating = True
.EnableEvents = True
End With
End Sub
Function LastRow(sh As Worksheet)
On Error Resume Next
LastRow = sh.Cells.Find(What:="*", _
After:=sh.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByRows, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Row
On Error GoTo 0
End Function
Function LastCol(sh As Worksheet)
On Error Resume Next
LastCol = sh.Cells.Find(What:="*", _
After:=sh.Range("A1"), _
Lookat:=xlPart, _
LookIn:=xlFormulas, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlPrevious, _
MatchCase:=False).Column
On Error GoTo 0
End Function
Also, see the link below for some other options to do this slightly differently.
http://www.rondebruin.nl/win/s3/win002.htm
I have maintained two Excel reports EPC1.xlsx and Control Power Transformers.xlsm respectively.
I want to trigger an button click from Control Power Transformers.xlsm report where it will search for "CTPT" term in "A" column from EPC1.xlsx, once it finds the term it need to copy Column B and Column c till the row ends (in EPC1.xlsx) and paste it in Control Power Transformers.xlsm workbook
I am successful in retrieving the cell address of "CTPT" term but how to select the data from adjacent column B and C?
And this is what I have tried
Private Sub CommandButton23_Click()
Dim rngX As Range
Dim num As String
Windows("EPC 1.xlsx").Activate
Set rngX = Worksheets("Sheet1").Range("A1:A10000").Find("CTPT", Lookat:=xlPart)
num = rngX.Address ' Here we will the get the cell address of CTPT ($A$14)
Range(rngX, Range("C" & rngX.Row).End(xlDown)).Copy
Windows("Control Power Transformers.xlsm").Activate
Sheets("Sheet2").Select
ActiveSheet.Range("E2").PasteSpecial (xlPasteValues)
End Sub
Paste the below in sample workbook. The below code will help to select both files using file dialog. It will search for word "CTPT". if so it will copy the column values from CTPT sheet to control file.
Sub DetailsFilePath()
Dim File1 As String
Dim File2 As String
Dim findtext As String
Dim copyvalues As Long
Dim c As Variant
Dim wb1 As Workbook
Dim wb2 As Workbook
Dim ws1 As Worksheet
Dim ws2 As Worksheet
MsgBox "Open the CTPT file"
Application.FileDialog(msoFileDialogFilePicker).Show
'On Error Resume Next
' open the file
File1 = Application.FileDialog(msoFileDialogFilePicker).SelectedItems(1)
MsgBox "Open the Control Power Transformers file"
Application.FileDialog(msoFileDialogFilePicker).Show
File2 = Application.FileDialog(msoFileDialogFilePicker).SelectedItems(1)
Set wb1 = Workbooks.Open(Filename:=File1)
Set ws1 = wb1.Worksheets("sheet1")
Set wb2 = Workbooks.Open(Filename:=File2)
Set ws2 = wb2.Worksheets("sheet1")
findtext = "CTPT"
With ws1.Columns(1)
Set c = .Find(findtext, LookIn:=xlValues)
If Not c Is Nothing Then
copyvalues = c.Column
ws2.Columns(2).Value = ws1.Columns(2).Value
ws2.Columns(3).Value = ws1.Columns(3).Value
End If
End With
wb1.Close savechanges:=True
wb2.Close savechanges:=True
End Sub
You need to use FindNext to find other results, and the Offset will help you select what you want from the address of your results :
Sub test_Karthik()
Dim WbEPC As Workbook, _
WbCPT As Workbook, _
WsEPC As Worksheet, _
WsCPT As Worksheet, _
FirstAddress As String, _
WriteRow As Long, _
cF As Range, _
num As String
Set WbEPC = Workbooks("EPC 1.xlsx")
Set WbCPT = Workbooks("Control Power Transformers.xlsm")
Set WsEPC = WbEPC.Sheets("Sheet1")
Set WsCPT = WbCPT.Sheets("Sheet2")
With WsEPC
.Activate
With .Range("A1:A10000")
'First, define properly the Find method
Set cF = .Find(What:="CTPT", _
After:=ActiveCell, _
LookIn:=xlValues, _
Lookat:=xlPart, _
SearchOrder:=xlByColumns, _
SearchDirection:=xlNext, _
MatchCase:=False, _
SearchFormat:=False)
'If there is a result, keep looking with FindNext method
If Not cF Is Nothing Then
FirstAddress = cF.Address
Do
num = cF.Address ' Here we will the get the cell address of CTPT ($A$14)
WsEPC.Range(cF.Offset(0, 1), cF.Offset(0, 2).End(xlDown)).Copy
WriteRow = WsCPT.Range("E" & WsCPT.Rows.count).End(xlUp).Row + 1
WsCPT.Range("E" & WriteRow).PasteSpecial (xlPasteValues)
Set cF = .FindNext(cF)
'Look until you find again the first result
Loop While Not cF Is Nothing And cF.Address <> FirstAddress
End If
End With
End With
End Sub