What goes into the Excel Workbook object that increases file size? - vba

I am trying to reduce the file size of an Excel workbook I am using. I already know about unused rows being an issue and unnecessary images etc. The mystery is why there is a secret part of excel that only seems to grow?
I can discover the total size of my entire document with
Sub workbook_objectsize()
With CreateObject("Scripting.FileSystemObject")
Set wb = ActiveWorkbook
WBObjectSize = .GetFile(wb.fullname).Size
MsgBox (Format(WBObjectSize, "#,##0") & " Bytes")
End With
End Sub
and I can discover the size by sheet and the WB Object using
Sub GetSheetSizes()
' ZVI:2012-05-18 Excel VBA File Size by Worksheet in File
' CAR:2014-10-07 Enhanced to take hidden and very hidden sheets into account
Dim a() As Variant
Dim Bytes As Double
Dim i As Long
Dim fileNameTmp As String
Dim wb As Workbook
Dim visState As Integer
Set wb = ActiveWorkbook
ReDim a(0 To wb.Sheets.Count, 1 To 2)
' Turn off screen updating
Application.ScreenUpdating = False
On Error GoTo exit_
' Put names into a(,1) and sizes into a(,2)
With CreateObject("Scripting.FileSystemObject")
' Build the temporary file name
Err.Clear
fileNameTmp = .GetSpecialFolder(2) & "\" & wb.Name & ".TMP"
' Put workbook's name and size into a(0,)
a(0, 1) = wb.Name
a(0, 2) = .GetFile(wb.fullname).Size
' Put each sheet name and its size into a(i,)
For i = 1 To wb.Sheets.Count
visState = wb.Sheets(i).Visible
wb.Sheets(i).Visible = -1 ' Show sheet long enough to copy it
DoEvents
wb.Sheets(i).Copy
ActiveWorkbook.SaveCopyAs fileNameTmp
wb.Sheets(i).Visible = visState
a(i, 1) = wb.Sheets(i).Name
a(i, 2) = .GetFile(fileNameTmp).Size
Bytes = Bytes + a(i, 2)
ActiveWorkbook.Close False
Next
Kill fileNameTmp
End With
' Show workbook's name & size
Debug.Print a(0, 1), Format(a(0, 2), "#,##0") & " Bytes"
' Show workbook object's size
Debug.Print "Wb Object", Format(a(0, 2) - Bytes, "#,##0") & " Bytes"
' Show each sheet name and its size
For i = 1 To UBound(a)
Debug.Print a(i, 1), Format(a(i, 2), "#,##0") & " Bytes"
Next
exit_:
' Restore screen updating
Application.ScreenUpdating = True
' Show the reason of error if happened
If Err Then MsgBox Err.Description, vbCritical, "Error"
End Sub
Here is the exercise. I have MYWORKBOOK
step 1. check total file size and file size by sheet + wb object
MYWORKBOOK Ver0.34 test.xlsm 932,450 Bytes Total
Wb Object 201,679 Bytes
Home 312,904 Bytes
NISI_DETAIL 40,815 Bytes
DATABASE 49,186 Bytes
Settings 13,690 Bytes
NISI_LIST 27,484 Bytes
PleaseWait 21,232 Bytes
success 22,077 Bytes
Brands 34,721 Bytes
USER_LIST 26,819 Bytes
QUERY_LIST 37,880 Bytes
CAT_MAN_TOOLS 88,406 Bytes
Sheet1 9,997 Bytes
PROMO_LIST 45,560 Bytes
step 2. DELETE ALL SHEETS leaving only a new blank sheet1 and check again
MYWORKBOOK Ver0.34 test .xlsm 370,052 Bytes
Wb Object 361,589 Bytes
Sheet1 8,463 Bytes
Yes file size was reduced but thats because I deleted every sheet. However, this mysterious Wb Object actually got larger. What the hell??? nothing but a single blank sheet and a 370Kb file?????
BTW running this same test on a new workbook yeilds a Wb Object size of 0 Bytes.
TL;DR: What on earth is the Wb Object in the example above? Why does it keep growing? How can I reduce it back down to 0 Bytes?

For file reduction I use code but in your case I don't see that it will help based on what you have posted. I would be very keen to see the contents of the zip file per GSergs suggestion.
Here is my file reduction code if you want to try it but like I said, I don't see that it will get it as small as you are hoping but it's worth a try:
Sub LipoSuction2()
'Written by Daniel Donoghue 18/8/2009
'The purpose of this code is to offer an alternative to the original Liposuction code written by JBeaucaire for the MrExcel forums www.mrexcel.com
Dim ws As Worksheet
Dim CurrentSheet As String
Dim OldSheet As String
Dim Col As Long
Dim r As Long
Dim BottomrRow As Long
Dim EndCol As Long
'Begin addition 6/4/2010 for request: http://www.mrexcel.com/forum/showthread.php?p=2269274#post2269274
Dim Pic As Object
'End Addition 6/4/2010 for request: http://www.mrexcel.com/forum/showthread.php?p=2269274#post2269274
For Each ws In Worksheets
ws.Activate
'Put the sheets in a variable to make it easy to go back and forth
CurrentSheet = ws.Name
'Rename the sheet to its name with TRMFAT at the end
OldSheet = CurrentSheet & "TRMFAT"
ws.Name = OldSheet
'Add a new sheet and call it the original sheets name
Sheets.Add
ActiveSheet.Name = CurrentSheet
Sheets(OldSheet).Activate
'Find the bottom cell of data on each column and find the further row
For Col = 1 To Columns.Count 'Find the REAL bottom row
If Cells(Rows.Count, Col).End(xlUp).Row > BottomRow Then
BottomRow = Cells(Rows.Count, Col).End(xlUp).Row
End If
Next
'Find the end cell of data on each row that has data and find the furthest one
For r = 1 To BottomRow 'Find the REAL most right column
If Cells(r, Columns.Count).End(xlToLeft).Column > EndCol Then
EndCol = Cells(r, Columns.Count).End(xlToLeft).Column
End If
Next
'Copy the REAL set of data
Range(Cells(1, 1), Cells(BottomRow, EndCol)).Copy
Sheets(CurrentSheet).Activate
'Paste everything
Range("A1").PasteSpecial xlPasteAll
'Paste Column Widths
Range("A1").PasteSpecial xlPasteColumnWidths
'Begin addition 6/4/2010 for request: http://www.mrexcel.com/forum/showthread.php?p=2269274#post2269274
Sheets(OldSheet).Activate
For Each Pic In ActiveSheet.Pictures
Pic.Copy
Sheets(CurrentSheet).Paste
Sheets(CurrentSheet).Pictures(Pic.Index).Top = Pic.Top
Sheets(CurrentSheet).Pictures(Pic.Index).Left = Pic.Left
Next
Sheets(CurrentSheet).Activate
'End Addition 6/4/2010 for request: http://www.mrexcel.com/forum/showthread.php?p=2269274#post2269274
'Reset the variable for the next sheet
BottomRow = 0
EndCol = 0
Next
'Excel will automatically replace the sheet references for you on your formulas, the below part puts them back
'This is done with a simple reaplce, replacing TRMFAT with nothing
For Each ws In Worksheets
ws.Activate
Cells.Replace "TRMFAT", ""
Next
'Poll through the sheets and delete the original bloated sheets
For Each ws In Worksheets
If Not Len(Replace(ws.Name, "TRMFAT", "")) = Len(ws.Name) Then
Application.DisplayAlerts = False
ws.Delete
Application.DisplayAlerts = True
End If
Next
End Sub

I found some excel workbooks that had imported too much data resulting in worksheets with over 16k columns & 65k rows - Couldn't operate - found a way to delete columns & rows - trick was to start at the end, work backwards & save along the way. reduced filesize from 3mb to 125k.. Code below - read, test, and use at your own risks...
Function delsht()
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
Application.CutCopyMode = False
Sheet3.AutoFilterMode = False
DoEvents
Debug.Print Sheet3.UsedRange.Address
' c = psht.UsedRange.Columns(psht.UsedRange.Columns.Count).Column
' For i = c To 1500 Step -500
' psht.Range(Columns(i), Columns(i - 500)).Delete
' DoEvents
' ActiveWorkbook.Save
' Debug.Print i, Time()
' Next i
r = Sheet3.UsedRange.Rows(Sheet3.UsedRange.Rows.Count).Row
For i = r To 2000 Step -500
Sheet3.Range(Rows(i), Rows(i - 500)).Delete
DoEvents
ActiveWorkbook.Save
Debug.Print i, Time()
Next i
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
Debug.Print "done."
End Function
Function bloatfinder()
Dim sht As Worksheet
For Each sht In Application.ActiveWorkbook.Sheets
Debug.Print sht.Name, sht.UsedRange.Address,
c = sht.UsedRange.Columns(sht.UsedRange.Columns.Count).Column
r = sht.UsedRange.Rows(sht.UsedRange.Rows.Count).Row
Debug.Print " Rows:", r, "Cols:", c
Next
Set sht = Nothing
End Function

Related

VBA move row data to their related sheet but if duplicate row found then skip that row

I have a sheet named "RAW ITEMS" with data, and also have few more sheets with different name, where i need to move data from "RAW ITEMS" sheet. and all sheet name are available at sheet "RAW ITEMS" in Column C3 to C100.
When I run below code It's works good when I run it first time.
But when I add some data to Sheet "RAW ITEMS", It's also move earlier Rows to their related sheet. I can't figure out how to stop moving duplicate rows.
I mean how to skip if duplicate raw found in those sheets where data are moving?
Sub copyPasteData()
Dim PV As String
Dim ps As String
Dim LastRow As Long
PV = "RAW ITEMS"
Sheets(PV).Visible = True
Sheets(PV).Select
Range("C3").Select
Do While ActiveCell.Value <> ""
ps = ActiveCell.Value
ActiveCell.Offset(0, -2).Resize(1, ActiveCell.CurrentRegion.Columns.Count).Select
Selection.Copy
Sheets(ps).Visible = True
Sheets(ps).Select
LastRow = pvs("A")
Cells(LastRow + 1, 1).Select
Selection.PasteSpecial xlPasteValues
Application.CutCopyMode = False
Sheets(PV).Select
ActiveCell.Offset(0, 2).Select
ActiveCell.Offset(1, 0).Select
Loop
Range("A1").Select
End Sub
Public Function pvs(col)
Dim LastRow As Long
With ActiveSheet
LastRow = .Cells(.Rows.Count, col).End(xlUp).Row
End With
pvs = LastRow
End Function
I am newbies in VBA. Please help me.
how to skip if duplicate raw found in those sheets where data are moving?
This is the file link for better understand
Try the next code, please. It avoids any selection, activation which consumes Excel resources, without bringing any benefit. It should be fast, using arrays and working in memory:
Sub copyPasteData()
Dim PVWs As Worksheet, PSWs As Worksheet, arrPV, arrPS, arPV, arPS
Dim LastRPv As Long, LastRPs As Long, lastCol As Long, i As Long
Dim j As Long, boolCopy As Boolean
Set PVWs = Worksheets("RAW ITEMS")
LastRPv = PVWs.Range("C" & Rows.Count).End(xlUp).Row
lastCol = PVWs.UsedRange.Columns.Count
'load the range in an array:
arrPV = PVWs.Range(PVWs.Range("A" & 2), PVWs.Cells(LastRPv, lastCol)).Value
For i = 1 To UBound(arrPV) 'iterate between the array rows
On Error Resume Next
Set PSWs = Worksheets(CStr(arrPV(i, 3))) 'set the sheet to paste, if no a similar row exists
If Err.Number = 9 Then
Err.Clear: On Error GoTo 0
Dim ans As VbMsgBoxResult
ans = MsgBox("The sheet " & CStr(arrPV(i, 3)) & " does not exist!" & vbCrLf & _
"Would you like to create it?", vbYesNo, "Sheet creation confirmation")
If ans <> vbYes Then GoTo OverIt
Set PSWs = Worksheets.Add(after:=Worksheets(Worksheets.Count)) 'add the new sheet (after the last)
PSWs.Name = arrPV(i, 3) 'name the newly inserted sheet
'copy the header from the previous sheet:
PSWs.Previous.Range("A1:G1").Copy Destination:=PSWs.Range("A1")
End If
On Error GoTo 0
arPV = Application.Index(arrPV, i, 0) 'a slice of the i row (1D array)
LastRPs = PSWs.Range("A" & Rows.Count).End(xlUp).Row 'last row
'load the sheet existing range in an array
arrPS = PSWs.Range(PSWs.Range("A" & 1), PSWs.Cells(LastRPs, lastCol)).Value
For j = 1 To UBound(arrPS) ' iterate and check if the sliced rows are all the elements identic
boolCopy = True
arPS = Application.Index(arrPS, j, 0) 'a slice of the j row (1D array)
If Join(arPV, "|") = Join(arPS, "|") Then 'check if the rows are the same
boolCopy = False: Exit For
End If
Next j
If boolCopy Then
'if not alsready in the sheet, the array is copied
PSWs.Range("A" & LastRPs + 1).Resize(1, UBound(arPV)).Value = arPV
boolCopy = False 'reinitialize the Boolean variable
End If
OverIt:
Next i
End Sub
The code logic assumes that "duplicate row" means that all the cells values on a sheet to copy row are identic whit the one of the analyzed row to be copied.
And in the C column the sheet itself name should exist...

Save workbook as CSV with UTF-8 encoding

How can I save my workbook as CSV without losing UTF-8 characters?
So far, this the my code of saving workbook as CSV:
Option Explicit
Public wb As Workbook, ws As Worksheet, venture As String, intl As String, SvPath As String
Private Function chopFilesThenSave()
Dim NumOfColumns As Long
Dim RangeToCopy As Range
Dim RangeOfHeader As Range 'data (range) of header row
Dim WorkbookCounter As Integer
Dim RowsInFile 'how many rows (incl. header) in new files?
Dim p As Long
'Initialize data
Set ws = ThisWorkbook.Sheets("MixedNuts")
NumOfColumns = ws.UsedRange.Columns.Count
WorkbookCounter = 1
RowsInFile = 2000 + 1 'how many rows (incl. header in new files?
'Check if the folder provided is exist, else create one!
If Len(Dir(SvPath & "batch\", vbDirectory)) = 0 Then
MkDir SvPath & "batch\"
End If
'Copy the data of the first row (header)
Set RangeOfHeader = ws.Range(ws.Cells(1, 1), ws.Cells(1, NumOfColumns))
For p = 2 To ThisWorkbook.Sheets("Mixed").UsedRange.Rows.Count Step RowsInFile - 1
Set wb = Workbooks.Add
'Paste the header row in new file
RangeOfHeader.Copy wb.Sheets(1).Range("A1")
wb.Sheets(1).Range("A:B").NumberFormat = "#" 'set column as text
'Paste the chunk of rows for this file
Set RangeToCopy = ws.Range(ws.Cells(p, 1), ws.Cells(p + RowsInFile - 2, NumOfColumns))
RangeToCopy.Copy
wb.Sheets(1).Range("A2").PasteSpecial xlPasteValues
'Save the new workbook, and close it
wb.SaveAs SvPath & "batch\" & venture & intl & "BatchUpdate_" & Format(Now, "mmDDYYYY") & "-" & WorkbookCounter & ".csv", xlCSV
wb.Close False
'Increment file counter
WorkbookCounter = WorkbookCounter + 1
Next p
Set wb = Nothing
End Function
The code runs in a loop where I cut 2,000 rows (excluding headers) from sheet "MixedNuts", copy and paste to a new workbook then save it as CSV and do this again on the next row. But again, the problem is after saving it as CSV, utf-8 characters became question marks.

Excel VBA, Paste special adds trailing zeroes

I have raw data from ANSYS mechanical exported as .xml with the following format (2 rows, x number of columns):
Steps Time [s] [A] C1 (Total) [N]
1 1 1, 4,4163e+005
I have a lot of files and I'm trying to combine these into one table in Excel using VBA. The script works fine with one exception, it does not interpret the scientific format correctly. My result is as follows:
Steps 1
Time [s] 1
[A] C1 (Total) [N] 4,42E+09
Code looks as follows:
Private Sub CommandButton1_Click()
Dim directory As String, fileName As String, sheet As Worksheet, total As Integer
Dim wb1 As Excel.Workbook
Dim wb2 As Excel.Workbook
Set wb1 = ThisWorkbook
wb1.Sheets("Sheet1").Cells.ClearContents
'define table headers on row 1
wb1.Sheets("Sheet1").Range("A1:A1").Value = "Load Case"
wb1.Sheets("Sheet1").Range("B1:B1").Value = "Load Case"
wb1.Sheets("Sheet1").Range("C1:C1").Value = "Load Case"
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'directory of source files
directory = "C:\Users\xxxxxxx\Ansysxls\"
fileName = Dir(directory & "*.xl??")
'Define the last used row in the target sheet
LastRow = wb1.Sheets("Sheet1").Cells(wb1.Sheets("Sheet1").Rows.Count, "B").End(xlUp).Row + 1
Do While fileName = "Asymmetric.xls"
'define which workbook to open
Set wb2 = Workbooks.Open(directory & fileName)
'loop through sheets in source file
For Each sheet In Workbooks(fileName).Worksheets
'Select range in source file
wb2.Sheets(sheet.Name).Range("A1").CurrentRegion.Select
'Replace commas with dot
Selection.Replace What:=",", Replacement:=".", LookAt:=xlPart, _
SearchOrder:=xlByRows, MatchCase:=False
Selection.Copy
'Paste Special to target file <-----Smth wrong in my paste special???
wb1.Sheets("Sheet1").Range("B" & LastRow).PasteSpecial _
Paste:=xlPasteValuesAndNumberFormats, SkipBlanks:=True, Transpose:=True
wb2.Sheets(sheet.Name).Activate
Next sheet
'define first row and last row of last import and add from what file the came
FirstRow = LastRow
LastRow = wb1.Sheets("Sheet1").Cells(wb1.Sheets("Sheet1").Rows.Count, "B").End(xlUp).Row + 1
'remove file ending ".xls" from column
wb1.Sheets("Sheet1").Range("A" & FirstRow & ":" & "A" & LastRow).Value = Left(fileName, Len(fileName) - 4)
Workbooks(fileName).Close
fileName = Dir()
Loop
Application.ScreenUpdating = True
Application.DisplayAlerts = True
'Create Table
wb1.Sheets("Sheet1").ListObjects.Add(xlSrcRange, Sheets("Sheet1").Range("A1").CurrentRegion, , xlYes, Header = xlYes).Name = "myTable1"
End Sub
Can anybody help me understand why it changes with from e+5 to e+9?
Excel will 'interpret' the Total [N]) value (which has the comma in it) depending on the numbering system of your Excel application.
I believe if you paste a value of 4,4163e+005 into your worksheet, you will see a value of 4416300000, assuming your thousands are comma separated. In your case, however, you seem to want to convert the comma to a decimal point so that the true value is 441630. This can only be done if the value is a string, but yours probably isn't, it's most likely a number. I'm afraid I rather suspect your search and replace line makes no changes at all.
Although I can't see the values themselves, my bet would be that you need to divide each value by 10000 and then set the number format of your cells to "0.0000E+00".
I've put some code below that will loop through the values and make that change for you. You'll see that I've assumed each sheet only contains the 2 x 4 cell size, so adjust this if you need to.
Other comments about your code:
I think you need to put your last row update within the sheet loop. At a quick glance it looks as though you might be overwriting previous sheet data (ie the only data being written to your target is the source's last sheet data).
I'm not sure what you're intentions are with the Dir() function and then checking for a unique filename. It looks to me as if that will only loop once on a file called "Asymmetric.xls". If this is what you want then just define that workbook as an object. If you want to read all the workbooks in the directory then you need to run the Dir() loop until filename = "". That's what I've assumed in my code.
Private Sub CommandButton1_Click()
Dim directory As String
Dim fileName As String
Dim source As Workbook
Dim sht As Worksheet
Dim targetRng As Range
Dim rawValues As Variant
Dim revisedValues() As Variant
Dim rDimension As Long
Dim cDimension As Integer
Dim r As Long
Dim c As Integer
Application.ScreenUpdating = False
Application.DisplayAlerts = False
'define table headers on row 1
With ThisWorkbook.Sheets("Sheet1")
.Cells.ClearContents
.Cells(1, 1).Resize(, 3).Value = _
Array("Filename", "Item", "Value")
Set targetRng = .Cells(2, 2) 'ie "B2"
End With
'Directory of source files
directory = "C:\Users\xxxxxxx\Ansysxls\"
fileName = Dir(directory & "*.xl??")
Do Until fileName = ""
'define which workbook to open
Set source = Workbooks.Open(directory & fileName)
'loop through sheets in source file
For Each sht In source.Worksheets
'Select range in source file
If Not IsEmpty(sht.Range("A1")) Then
rawValues = sht.Range("A1").CurrentRegion.Value2
' Manipulate the acquired data
rDimension = UBound(rawValues, 1)
cDimension = UBound(rawValues, 2)
' Transpose the dimensions and manipulate the totalN value
ReDim revisedValues(1 To cDimension, 1 To rDimension)
For r = 1 To rDimension
For c = 1 To cDimension
If r = 2 And c = 4 Then ' it's totalN
' Convert the data to a LongLong and divide by 10000
revisedValues(c, r) = CLngLng(rawValues(r, c)) / 10000
Else
revisedValues(c, r) = rawValues(r, c)
End If
Next
Next
'Populate the target sheet with revised values
Set targetRng = targetRng.Resize(cDimension, rDimension)
targetRng.Value2 = revisedValues
' Define the scientific format
targetRng.Cells(4, 2).NumberFormat = "0.0000E+00"
' Add the filename to column "A"
targetRng.Offset(, -1).Resize(, 1).Value2 = _
Left(fileName, (InStrRev(fileName, ".", -1, vbTextCompare) - 1))
' Move the targetRng to the bottom of this range
Set targetRng = targetRng.Offset(targetRng.Rows.Count)
End If
Next
source.Close
fileName = Dir()
Loop
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub

search a worksheet for all value VBA Excel

I have a worksheet that has multiple value and what I would like to do is search say column "B" for a value and when it finds it to copy the complete row and paste it somewhere else. I have a similar function to do this but it stops after it finds the first one which is fine for the situation that I am using it in but for this case I need it to copy all that match. below is the code that im using at the moment that only gives me one value
If ExpIDComboBox.ListIndex <> -1 Then
strSelect = ExpIDComboBox.value
lastRow = wks1.range("A" & Rows.Count).End(xlUp).row
Set rangeList = wks1.range("A2:A" & lastRow)
On Error Resume Next
row = Application.WorksheetFunction.Match(strSelect, wks1.Columns(1), 0) ' searches the worksheet to find a match
On Error GoTo 0
If row Then
Thanks
I would suggest to load data into array first and then operate on this array instead of operating on cells and using Worksheet functions.
'(...)
Dim data As Variant
Dim i As Long
'(...)
If ExpIDComboBox.ListIndex <> -1 Then
strSelect = ExpIDComboBox.Value
lastRow = wks1.Range("A" & Rows.Count).End(xlUp).Row
'Load data to array instead of operating on worksheet cells directly - it will improve performance.
data = wks1.Range("A2:A" & lastRow)
'Iterate through all the values loaded in this array ...
For i = LBound(data, 1) To UBound(data, 1)
'... and check if they are equal to string [strSelect].
If data(i, 1) = strSelect Then
'Row i is match, put the code here to copy it to the new destination.
End If
Next i
End If
I have used the Range.Find() method to search each row. For each row of data which it finds, where the value you enter matches the value in column G, it will copy this data to Sheet2. You will need to amend the Sheet variable names.
Option Explicit
Sub copyAll()
Dim rngFound As Range, destSheet As Worksheet, findSheet As Worksheet, wb As Workbook
Dim strSelect As String, firstFind As String
Set wb = ThisWorkbook
Set findSheet = wb.Sheets("Sheet1")
Set destSheet = wb.Sheets("Sheet2")
strSelect = ExpIDComboBox.Value
Application.ScreenUpdating = False
With findSheet
Set rngFound = .Columns(7).Find(strSelect, LookIn:=xlValues)
If Not rngFound Is Nothing Then
firstFind = rngFound.Address
Do
.Range(.Cells(rngFound.Row, 1), .Cells(rngFound.Row, _
.Cells(rngFound.Row, .Columns.Count).End(xlToLeft).Column)).Copy
destSheet.Cells(destSheet.Cells(Rows.Count, 1).End(xlUp).Row + 1, 1).PasteSpecial Paste:=xlPasteAll
Set rngFound = .Columns(2).Find(strSelect, LookIn:=xlValues, After:=.Range(rngFound.Address))
Loop While firstFind <> rngFound.Address
End If
End With
Application.ScreenUpdating = True
End Sub
I've assumed you will have data between columns A:G?
Otherwise you can just amend the .Copy and .PasteSpecial methods to fit your requirements.
Thanks for your replys. I tired to use both methods but for some reason they did not seem to work. They did not give me an error they just did not produce anything.#mielk I understand what you mean about using an array to do this and it will be a lot faster and more efficent but I dont have enfough VBA knowledge to debug as to why it did not work. I tried other methods and finally got it working and thought it might be usefull in the future for anybody else trying to get this to work. Thanks once again for your answers :)
Private Sub SearchButton2_Click()
Dim domainRange As range, listRange As range, selectedString As String, lastRow As Long, ws, wks3 As Excel.Worksheet, row, i As Long
Set wks3 = Worksheets("Exceptions") '<----- WorkSheet for getting exceptions
If DomainComboBox.ListIndex <> -1 Then '<----- check that a domain has been selected
selectedString = DomainComboBox.value
lastRow = wks3.range("A" & Rows.Count).End(xlUp).row ' finds the last full row
Set listRange = wks3.range("G2:G" & lastRow) 'sets the range from the top to the last row to search
i = 2
'used to only create a new sheet is something is found
On Error Resume Next
row = Application.WorksheetFunction.Match(selectedString, wks3.Columns(7), 0) ' searches the worksheet to find a match
On Error GoTo 0
If row Then
For Each ws In Sheets
Application.DisplayAlerts = False
If (ws.Name = "Search Results") Then ws.Delete 'deletes any worksheet called search results
Next
Application.DisplayAlerts = True
Set ws = Sheets.Add(After:=Sheets(Sheets.Count)) 'makes a new sheet at the end of all current sheets
ws.Name = "Search Results" 'renames the worksheet to search results
wks3.Rows(1).EntireRow.Copy 'copys the headers from the exceptions page
ws.Paste (ws.Cells(, 1)) 'pastes the row into the search results page
For Each domainRange In listRange ' goes through every value in worksheet trying to match what has been selected
If domainRange.value = selectedString Then
wks3.Rows(i).EntireRow.Copy ' copys the row that results was found in
emptyRow = WorksheetFunction.CountA(ws.range("A:A")) + 1 ' finds next empty row
ws.Paste (ws.Cells(emptyRow, 1)) 'pastes the contents
End If
i = i + 1 'moves onto the next row
ws.range("A1:Q2").Columns.AutoFit 'auto fit the columns width depending on what is in the a1 to q1 cell
ws.range("A1:Q1").Cells.Interior.ColorIndex = (37) 'fills the header with a colour
Application.CutCopyMode = False 'closes the paste funtion to stop manual pasting
Next domainRange ' goes to next value
Else
MsgBox "No Results", vbInformation, "No Results" 'display messgae box if nothing is found
Exit Sub
End If
End If
End Sub
Thanks.
N.B. this is not the most efficent way of doing this read mielk's answer and the other answer as they are better if you can get them working.

Excel Vba: Creating loop that checks if the values in column A matches and copy all the rows to a new spreadsheet

I need to select all the rows in column A that have the same the value and paste them to a new spreadsheet named with the copied name.
In the example picture when I run macro and input value Banana I should get all the rows that contain banana in column A.
I found following vba code from the internet and tried to modify it to my needs but I'm stuck:
Sub LookForAllSameValues()
Dim LSearchRow As Integer
Dim LCopyToRow As Integer
On Error GoTo Err_Execute
'Start search in row 4
LSearchRow = 2
'Start copying data to row 2 in Sheet2 (row counter variable)
LCopyToRow = 2
Uname = InputBox("Test")
ActiveWorkbook.Worksheets.Add.Name = Uname
While Len(Range("A" & CStr(LSearchRow)).Value) > 0
'If value in column E = "Mail Box", copy entire row to Sheet2
If Range("A" & CStr(LSearchRow)).Value = Uname Then
'Select row in Sheet1 to copy
Rows(CStr(LSearchRow) & ":" & CStr(LSearchRow)).Select
Selection.Copy
'Paste row into Sheet2 in next row
Sheets(Uname).Select
Rows(CStr(LCopyToRow) & ":" & CStr(LCopyToRow)).Select
ActiveSheet.Paste
'Move counter to next row
LCopyToRow = LCopyToRow + 1
'Go back to Sheet1 to continue searching
Sheets("Sheet1").Select
End If
LSearchRow = LSearchRow + 1
Wend
'Position on cell A3
Application.CutCopyMode = False
Range("A3").Select
MsgBox "All matching data has been copied."
Exit Sub
Err_Execute:
MsgBox "An error occurred."
End Sub
This code almost works. It asks user to input string to search and then it creates a new worksheet named as this one. The problem lies in the loop, I debugged the code and for some reason it just skips copy paste loop
How do I get the loop working?
Output when the code is run:
I'm assuming you're testing this on the data shown above.
Your code states that LSearch Row = 2 and therefore your search will begin in cell A2. I'd therefore assume your loop is never executing because Len(Range("A2")) equals 0 (the cell is empty) and the loop immediately exits. This also means that if any cell in column A is empty the loop will end there even if there is more data below it.
Instead try using a For..Next loop as shown below which will run from row 2 to the last used row in the active sheet, regardless of the cell contents.
Public Sub FindAndCreateNew()
Dim strFind As String
Dim i As Long, j As Long
Dim wsFind As Worksheet
Dim wsPaste As Worksheet
'Get value to search for
strFind = InputBox("Test")
'Create object reference to the current worksheet
Set wsFind = ActiveSheet
'Create a new worksheet with object reference and then rename it
Set wsPaste = Worksheets.Add
wsPaste.Name = strFind
'Paste starting at row 2 in wsPaste
j = 2
'Start searching from row 2 of wsFind, continue to end of worksheet
For i = 2 To wsFind.UsedRange.Rows.Count
If wsFind.Range("A" & i) = strFind Then
'Copy row i of wsFind to row j of wsPaste then increment j
wsFind.Range(i & ":" & i).Copy Destination:=wsPaste.Range(j & ":" & j)
j = j + 1
End If
Next i
End Sub
P.S. It's also worth noting that the use of .Select is generally avoidable and it can slow the program down considerably as well as making it less readable. For example this:
'Select row in Sheet1 to copy
Rows(CStr(LSearchRow) & ":" & CStr(LSearchRow)).Select
Selection.Copy
Could be represented with just one statement as below:
'Select row in Sheet1 to copy
Rows(CStr(LSearchRow) & ":" & CStr(LSearchRow)).Copy
As commented, try this:
Sub test()
Dim sh1 As Worksheet, sh2 As Worksheet
Dim rng As Range
Dim uname As String
Set sh1 = Sheet1: uname = InputBox("Input")
With Application
.ScreenUpdating = False
.DisplayAlerts = False
End With
If Len(uname) = 0 Then MsgBox "Invalid input": Exit Sub
Set sh2 = ThisWorkbook.Sheets.Add(after:= _
ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
On Error Resume Next
sh2.Name = uname: If Err.Number <> 0 Then MsgBox "Data already copied": _
sh2.Delete: Exit Sub
On Error GoTo 0
With sh1
.AutoFilterMode = False
Set rng = .Range("A1", .Range("A" & .Rows.Count).End(xlUp))
rng.AutoFilter 1, uname
On Error Resume Next
rng.SpecialCells(xlCellTypeVisible).EntireRow.Copy sh2.Range("A1")
If Err.Number <> 0 Then MsgBox "Data not found" _
Else MsgBox "All matching data has been copied"
.AutoFilterMode = False
On Error GoTo 0
End With
With Application
.ScreenUpdating = True
.DisplayAlerts = True
End With
End Sub