I am trying to understand why I get Type mismatch error:
This is the function I have, basically it is copying from a worksheet to another and afterwards deleting the first character of the copied cells:
Sub copyBackFormulas()
Application.ScreenUpdating = False
Application.EnableEvents = False
'iterate through all worksheets
Dim WS_Count As Integer
WS_Count = ActiveWorkbook.Worksheets.Count
Dim I As Integer
For I = 1 To WS_Count
Dim ws1 As Worksheet
Set ws1 = ThisWorkbook.Worksheets(I)
'if sheet contains evdre
Set d = ws1.Cells.Find("EVDRE:OK")
If Not d Is Nothing Then
'copy back all formulas except from current view
Dim wsTarget As Worksheet
Set wsTarget = ws1
nameHidden = ActiveSheet.Name & "_BPCOffline"
Sheets(nameHidden).Visible = True
Dim wsSource As Worksheet
Set wsSource = Sheets(nameHidden)
For Each c In wsSource.UsedRange.Cells
If Left(c.Value, 1) = "_" Then
If Left(c.Value, 7) = "_=EVCVW" Then
Else
c.Copy wsTarget.Range(c.Address)
End If
End If
Next
'Remove underscore
For Each c In wsTarget.UsedRange.Cells
If Left(c.Value, 1) = "_" Then
c.Formula = Right(c.Value, Len(c.Value) - 1)
End If
Next
wsSource.Visible = xlSheetHidden
End If
Range("A1").Select
Next I
Application.CutCopyMode = False
Application.ScreenUpdating = True
Application.EnableEvents = True
End Sub
I have several sheets that may need to be copied. The point is that I get type mismatch error on the line: If Left(c.Value, 1) = "_" Then
However, if I run the macro starting from other sheet it just works perfectly or it is only doing the right operations on one of the sheets and not the others.
I don't understand what makes it work at some point and what not.
Any input is highly appreciated
EDIT: I think the issue has to do with the fact that the macro may not find the first condition If Left(c.Value, 1) = "_" Then
You CAN'T copy paste formulas which have an error value
If you want to skip cells with errors you need another If...End if block:
If Not Iserror(c.Value) Then
...
End if
As explained by Rory in the comments
Related
I am fairly new to VBA and Wondering if someone can help me out.
I have 2 different sheets in a workbook.
Sheet(Raw Data) has a range with Cost Center NameS (Cell BC3 down to empty)
I have to copy Sheet(CC Template) and name it the right 5 characters of Sheet(Raw Data).Range(BC3).Value and change Cell(2,2).value to Sheet(Raw Data).Range(BC3).Value...
Then I want it to go to the next cell in Sheet(Raw Data) ...BC4 and create the second sheet and change the name and Cell(2,2) accordingly until the list in Sheet(Raw Data) ends.
Here is my Code. It creates the first worksheet but then I get run-time Error '1004' at Sheets("Raw Data").Range("BC3").Select in the do until loop. I would like to get rid of X and CCName variable from the code also if possible.
Sub CreateCCTabsinNewPlantFile2()
Dim i As Integer
Dim x As Integer
Dim CCName As String
i = ActiveWorkbook.Worksheets.Count
x = 1
' Select cell BC3, *first line of data*.
Sheets("Raw Data").Range("BC3").Select
' Set Do loop to stop when an empty cell is reached.
Do Until IsEmpty(ActiveCell)
CCName = ActiveCell.Value
' Code to make worksheets
Worksheets("CC Template").Copy after:=Worksheets(i)
ActiveSheet.Name = Right(CCName, 5)
ActiveSheet.Cells(2, 2).Value = CCName
' Step down 1 row from present location.
Sheets("Raw Data").Range("BC3").Select
ActiveCell.Offset(x, 0).Select
x = x + 1
Loop
End Sub
Sub CreateCCTabsinNewPlantFile2()
Dim i As Integer
Dim X As Integer
X = 3 'Starting row in Sheet("Raw Data")
With ThisWorkbook.Sheets("Raw Data")
Do Until .Cells(X, 55).Value = "" 'cells(x,55)= BC3. First time x= 3 so Cells(3,55)=BC3
i = ThisWorkbook.Worksheets.Count 'we update count everytime, because we are adding new sheets
ThisWorkbook.Worksheets("CC Template").Copy after:=ThisWorkbook.Worksheets(i)
ThisWorkbook.ActiveSheet.Name = Right(.Cells(X, 55).Value, 5)
ThisWorkbook.ActiveSheet.Cells(2, 2).Value = .Cells(X, 55).Value
' We increade X. That makes check a lower rower in next loop.
X = X + 1
Loop
End With
End Sub
Hope this helps.
You get error1004 because you can use Range.Select only in Active Sheet. If you want to Select a Range in different Sheet, first you must Activate that sheet with Sheets("Whatever").Activate.
Also, I Updated your code so you can execute it from any sheet. Your code forces user to have Sheets ("Raw Data") as the ActiveSheet.
Try not use too much Select if you can avoid it. And also , try to get used to Thisworkbook instead of ActiveWorkbook. If you work always in same workbook, is not a problem, but if your macros operate several workbooks, you'll need to difference when to use each one.
Try this code
Sub Test()
Dim rng As Range
Dim cel As Range
With Sheets("Raw Data")
Set rng = .Range("BC3:BC" & .Cells(Rows.Count, "BC").End(xlUp).Row)
End With
Application.ScreenUpdating = False
For Each cel In rng
If Not SheetExists(cel.Value) Then
Sheets("CC Template").Copy After:=Sheets(Sheets.Count)
With ActiveSheet
.Name = Right(cel.Value, 5)
.Range("B2").Value = cel.Value
End With
End If
Next cel
Sheets("Raw Data").Activate
Application.ScreenUpdating = True
End Sub
Function SheetExists(sheetName As String) As Boolean
On Error Resume Next
SheetExists = (LCase(Sheets(sheetName).Name) = LCase(sheetName))
On Error GoTo 0
End Function
I know this has been asked lot of times but I'm having a trouble with VBA, I am very new to VBA.
I'm working with a single workbook that has a working worksheet. basically I need to sort the Currency column, currently have 14 currencies, I need loop through it (since currency may add through time depending on the customer) then copy the row with the criteria paste it to another sheet with its cell value.
my code below.
Option Explicit
Sub SortCurrency()
Dim rng As Range
Dim xCell As Range
Dim I As Long
Dim J As Long
I = Worksheets("Sheet1").UsedRange.Rows.Count
J = Worksheets("Sheet2").UsedRange.Rows.Count
If J = 1 Then
If Application.WorksheetFunction.CountA(Worksheets("Sheet2").UsedRange) = 0 Then J = 0
End If
Set rng = Worksheets("Sheet1").Range("AB2:AB" & I)
On Error Resume Next
Application.ScreenUpdating = False
For Each xCell In rng
If CStr(xCell.Value) = "USD" Then
Sheets.Add After:=Sheets(Sheets.Count)
Sheets(Sheets.Count).Name = xCell.Value
xCell.EntireRow.Copy Destination:=Sheets(Sheets.Count).Name = xCell.Value.Range("A" & J + 1)
'Sheets.Add After:=Sheets(Sheets.Count)
'Sheets(Sheets.Count).Name = xCell.Value
Application.CutCopyMode = False
J = J + 1
End If
Next
Application.ScreenUpdating = True
End Sub
I basically got the codes from my research, add them up and not coming into the way I wanted. I wanted to keep the header and the values with criteria,
i,e currency column "AB" is USD as per example above, but the problem is it'll be a lot of coding because I have to go through all 14 currencies plus if there will be new currency that will be added,
also I know there is a way of not declaring multiple sheets and just having another new worksheet with the cell value name but I'm having a problem getting it done all at once. if there will be a simpler and powerful code. I am greatly thankful.
you may want to try this code, exploiting Autofilter() method of Range object
Option Explicit
Sub SortCurrency()
Dim currRng As Range, dataRng As Range, currCell As Range
With Worksheets("Currencies") '<--| change "Currencies" to your actual worksheet name to filter data in and paste from
Set currRng = .Range("AB1", .Cells(.Rows.Count, "AB").End(xlUp))
Set dataRng = Intersect(.UsedRange, currRng.EntireRow)
With .UsedRange
With .Resize(1, 1).Offset(, .Columns.Count)
With .Resize(currRng.Rows.Count)
.Value = currRng.Value
.RemoveDuplicates Array(1), Header:=xlYes
For Each currCell In .SpecialCells(xlCellTypeConstants)
currRng.AutoFilter field:=1, Criteria1:=currCell.Value
If Application.WorksheetFunction.Subtotal(103, currRng) - 1 > 0 Then
dataRng.SpecialCells(xlCellTypeVisible).Copy Destination:=GetOrCreateWorksheet(currCell.Value).Range("A1")
End If
Next currCell
.ClearContents
End With
End With
End With
.AutoFilterMode = False
End With
End Sub
Function GetOrCreateWorksheet(shtName As String) As Worksheet
On Error Resume Next
Set GetOrCreateWorksheet = Worksheets(shtName)
If GetOrCreateWorksheet Is Nothing Then
Set GetOrCreateWorksheet = Worksheets.Add(After:=Sheets(Sheets.Count))
GetOrCreateWorksheet.name = shtName
End If
End Function
You're pretty close with what you've got, but there's a few things to note:
On Error Resume Next is normally a bad plan as it can hide a whole lot of sins. I use it in the code below, but only because I immediately deal with any error that might have happened.
xCell.Value.Range("A" & J + 1) makes no sense. Chop out the middle of that line to leave xCell.EntireRow.Copy Destination:=Sheets(Sheets.Count).Range("A" & J + 1)
Rather than checking if the value is a specific currency, you should be taking the value, whatever currency it is, and dealing with it appropriately.
Using J as a counter works for one currency, but when dealing with multiple, it'll be easier to just check where it should go on the fly.
All told, the below code should be close to what you're looking for.
Option Explicit
Sub SortCurrency()
Dim rng As Range
Dim xCell As Range
Dim targetSheet As Worksheet
Dim I As Long
Dim J As Long
I = Worksheets("Sheet1").UsedRange.Rows.Count
J = Worksheets("Sheet2").UsedRange.Rows.Count
If J = 1 Then
If Application.WorksheetFunction.CountA(Worksheets("Sheet2").UsedRange) = 0 Then J = 0
End If
Set rng = Worksheets("Sheet1").Range("AB2:AB" & I)
Application.ScreenUpdating = False
For Each xCell In rng
Set targetSheet = Nothing
On Error Resume Next
Set targetSheet = Sheets(xCell.Value)
On Error GoTo 0
If targetSheet Is Nothing Then
Sheets.Add After:=Sheets(Sheets.Count)
Set targetSheet = Sheets(Sheets.Count)
targetSheet.Name = xCell.Value
xCell.EntireRow.Copy Destination:=targetSheet.Range("A" & J + 1)
Else
xCell.EntireRow.Copy Destination:=targetSheet.Range("A" & targetSheet.Range("A" & Rows.Count).End(xlUp).Row + 1)
End If
Application.CutCopyMode = False
Next
Application.ScreenUpdating = True
End Sub
OK, there's quite a lot going on here... I'm going to try and tackle one problem at a time.
1 - You could do with testing whether a worksheet already exists rather than creating it every time
Assuming you want to do something for each and every currency in your loop, I would suggest not using the if condition you're using at the moment, "if value = "USD"", and instead use the cell value to determine the name of the sheet, whatever the cell value is.
First of all you need a seperate function to test whether the sheet exists, like
Public Function DoesSheetExist(SheetName as String)
On Error Resume Next
Dim WkSheet as WorkSheet
'sets worksheet to be the sheet NAMED the current currency name
Set WkSheet = Sheets(SheetName)
'because of on error resume next, WkSheet will simply be "Nothing" if no such sheet exists
If WkSheet is Nothing Then
DoesSheetExist = False
Else
DoesSheetExist = True
End If
End Function
You can then call this function in your code, and only create new sheets when you need to
2 - The loop itself
So instead, I would suggest your loop probably wants to look more like this:
Dim xSheet as Worksheet 'declare this outside the loop
For Each xCell In rng
If DoesSheetExist(xCell.Value) Then
set xSheet = Sheets(xCell.Value) 'this is the code for if the sheet does exist - sets the sheet by the sheet name rather than index
Else
set xSheet = Sheets.Add After:=Sheets(Sheets.Count)
xSheet.Name = xCell.Value
End if
With this setup, for every currency your loop will either set xSheet to the currency sheet that already exists, or create that sheet. This assumes that you want to do the same thing to all currencies, if not then extra conditions will need adding in
3 - the copy/paste line itself
xCell.EntireRow.Copy Destination:=Sheets(Sheets.Count).Name = xCell.Value.Range("A" & J + 1)
I don't think this code says what you think it does - what this code actually says is "Copy the Entire Row to the last Sheet's name, and make it equal to the range within xCell's Value at A, (J)+1
I think what you actually wanted to say was this:
xCell.EntireRow.Copy Destination:=Sheets(Sheets.Count).Range("A" & J + 1)
However, if you're using the code I gave you above you can instead use this now:
xCell.EntireRow.Copy Destination:=xSheet.Range("A" & J + 1)
In fact, you'd be better off doing that, especially if there is a chance that the sheets already existed and were picked up by DoesSheetExist
Personally I would also rather transfer values over than use copy/paste any day, but that's just an efficiency thing, the above should function fine.
The script runs without errors but it doesn't do whats its supposed to do, In fact it doesn't change anything in the documents. I test a part and the testing software spits out 4 workbooks that are saved in a folder named Location 1,2,3,4. Then i open a template, "alpha" in the script, that uses data from the previous workbook to show averages and to show tread of data. The macro is then activated by a button and its supposed to paste in the alpha workbook to the next empty row. The rows are 6 cells apart and 3 cells across.
Apperently i need 10 rep before pictures so heres a link to the picture.... In the picture One test is done, i have a macro for one test (row) but i cant get it to repeat and paste to the next empty down. If there is a better way of doing this please let me know haha.
https://drive.google.com/file/d/0B9n6BtJ4Med8NlVGa2FySzEtMGM/view?usp=sharing
Sub DataTransfer()
'simplified to 2 workbooks
Dim w As Workbook 'Test_Location 1
Dim Alpha As Workbook 'Template
Dim Emptyrow As Range
Set w = Workbooks.Open("C:\Users\aholiday\Desktop\FRF_Data_Macro_Insert_Test\location_1.xls")
Set Alpha = Workbooks("FRF_Data_Sheet_Template.xlsm")
Set EmptyrowC = Range("C" & Alpha.Sheets("DataInput").UsedRange.Rows.Count + 1)
w.Sheets("Data").Range("I3:K7").Copy
With Alpha.Sheets("DataInput")
EmptyrowC.PasteSpecial Paste:=xlValues, Transpose:=False
Application.CutCopyMode = True
End With
End Sub
I also tried to do a If statement but got no where with that.
Sub DataTransfer()
Application.ScreenUpdating = False
Dim w As Workbook 'Test_Location 1
Dim x As Workbook 'Test_Location 2
Dim y As Workbook 'Test_Location 3
Dim z As Workbook 'Test_Location 4
Dim Alpha As Workbook 'Template
Dim Emptyrow As Long 'Next Empty Row
Set w = Workbooks.Open("C:\Users\aholiday\Desktop\FRF_Data_Macro_Insert_Test\location_1.xls")
Set x = Workbooks.Open("C:\Users\aholiday\Desktop\FRF_Data_Macro_Insert_Test\location_2.xls")
Set y = Workbooks.Open("C:\Users\aholiday\Desktop\FRF_Data_Macro_Insert_Test\location_3.xls")
Set z = Workbooks.Open("C:\Users\aholiday\Desktop\FRF_Data_Macro_Insert_Test\location_4.xls")
Set Alpha = Workbooks("FRF_Data_Sheet_Template.xlsm")
If Columns("C").Value = "" Then
Alpha.Sheets("DataInput").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Value = w.Sheets("Data").Range("I3:K7").Value
Alpha.Sheets("DataInput").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Value = x.Sheets("Data").Range("I3:K7").Value
Alpha.Sheets("DataInput").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Value = y.Sheets("Data").Range("I3:K7").Value
Alpha.Sheets("DataInput").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Value = z.Sheets("Data").Range("I3:K7").Value
w.Close False
x.Close False
y.Close False
z.Close False
End If
Application.ScreenUpdating = True
End Sub
Something like this:
Option Explicit
Sub DataTransfer()
Const FPATH As String = "C:\Users\aholiday\Desktop\FRF_Data_Macro_Insert_Test\"
Application.ScreenUpdating = False
Dim wb As Workbook
Dim shtAlpha As Worksheet 'Template
Dim locs, loc
Dim rngDest As Range
locs = Array("location_1.xls", "location_2.xls", _
"location_3.xls", "location_4.xls")
Set shtAlpha = Workbooks("FRF_Data_Sheet_Template.xlsm").Sheets("DataInput")
'set the first data block destination
Set rngDest = shtAlpha.Cells(Rows.Count, "C").End(xlUp).Offset(1, 0).Resize(5, 3)
For Each loc In locs
Set wb = Workbooks.Open(Filename:=FPATH & loc, ReadOnly:=True)
rngDest.Value = wb.Sheets("Data").Range("I3:K7").Value
wb.Close False
Set rngDest = rngDest.Offset(0, 3) 'move over to the right 3 cols
Next loc
Application.ScreenUpdating = True
End Sub
I'm not sure what you mean to do with that check on Column C, so I left that out...
I've made a number of (reasonable...?) assumptions and rewrote the first code to use the variables that are set and define the specific workbook that various range(s) originate on.
Sub DataTransfer()
Dim w As Workbook 'Test_Location 1
Dim x As Workbook 'Test_Location 2
Dim y As Workbook 'Test_Location 3
Dim z As Workbook 'Test_Location 4
Dim Alpha As Workbook 'Template
Dim EmptyrowC As Range, EmptyrowF As Range, EmptyrowI As Range, EmptyrowL As Range
Application.ScreenUpdating = False
Set w = Workbooks.Open("C:\Users\aholiday\Desktop\FRF_Data_Macro_Insert_Test\location_1.xls")
Set x = Workbooks.Open("C:\Users\aholiday\Desktop\FRF_Data_Macro_Insert_Test\location_2.xls")
Set y = Workbooks.Open("C:\Users\aholiday\Desktop\FRF_Data_Macro_Insert_Test\location_3.xls")
Set z = Workbooks.Open("C:\Users\aholiday\Desktop\FRF_Data_Macro_Insert_Test\location_4.xls")
Set Alpha = Workbooks("FRF_Data_Sheet_Template.xlsm")
With Alpha.Sheets("DataInput")
Set EmptyrowC = .Cells(Rows.Count, "C").End(xlUp).Offset(1, 0)
Set EmptyrowF = .Cells(Rows.Count, "F").End(xlUp).Offset(1, 0)
Set EmptyrowI = .Cells(Rows.Count, "I").End(xlUp).Offset(1, 0)
Set EmptyrowL = .Cells(Rows.Count, "L").End(xlUp).Offset(1, 0)
w.Sheets("Data").Range("I3:K7").Copy Destination:=EmptyrowC
x.Sheets("Data").Range("I3:K7").Copy Destination:=EmptyrowF
y.Sheets("Data").Range("I3:K7").Copy Destination:=EmptyrowI
z.Sheets("Data").Range("I3:K7").Copy Destination:=EmptyrowL
w.Close False
x.Close False
y.Close False
z.Close False
End With
Application.ScreenUpdating = True
End Sub
It's not 100% clear on whether you absolutely require a Range.PasteSpecial method so you get yo started, I've opted for the simpler Range.Copy method. If this is insufficient, then a direct value transfer would be preferred to a Copy, PasteSpecial, Values.
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.
Created a macro below thanks to help from another that works.
Basically, it takes the value of the cell in column A and, if a sheet doesn't exist with that cells name, creates it. Then it pastes all rows of data that have the corresponding cell value to that sheet. Ie. if a cell contains the following:
column a column b
dc00025 data value
If dc00025 doesn't exist, it'll make the sheet. And paste all rows with dc00025 in A.
This works perfectly. However, I noticed when you run this macro after a sheet has already been created, for some reason it adds thousands of columns dramatically slowing down excel.
To fix this, would it be possible to modify the script to only copy columns b:o rather tahnt he entire row? Pasting them starting at A3 would be preferable but I'm not sure how to fix that.
Thanks in advance.
Sub CopyCodes()
Application.ScreenUpdating = False
Dim rCell As Range
Dim lastrow As Long
lastrow = Sheets("Data").UsedRange.Rows.Count
For Each rCell In Worksheets("Data").Range("A2:A" & lastrow).SpecialCells(xlCellTypeConstants)
If Not SheetExists(rCell.Value) Then
With Worksheets.Add(, Worksheets(Worksheets.Count))
.Name = rCell.Value
End With
End If
Worksheets("Data").Rows(1).EntireRow.Copy Worksheets(rCell.Value).Rows(1)
Worksheets(rCell.Value).Range("A" & Rows.Count).End(xlUp)(2).EntireRow.Value = _
rCell.EntireRow.Value
Next rCell
Application.ScreenUpdating = True
End Sub
Function SheetExists(wsName As String)
On Error Resume Next
SheetExists = Worksheets(wsName).Name = wsName
End Function
Suggested fix:
Sub CopyCodes()
Application.ScreenUpdating = False
Dim rCell As Range
Dim lastrow As Long
Dim shtData as worksheet, shtDest as worksheet
Dim sheetName as string
set shtData=worksheets("Data")
lastrow = shtData.cells(rows.count,1).end(xlup).row
For Each rCell In shtData.Range("A2:A" & lastrow).SpecialCells(xlCellTypeConstants)
sheetName = rCell.Value
If Not SheetExists(sheetName) Then
set shtDest = Worksheets.Add(, Worksheets(Worksheets.Count))
shtDest.Name = sheetName
shtData.Rows(1).EntireRow.Copy shtDest.Rows(1)
Else
set shtDest = Worksheets(sheetName)
End If
shtDest.Range("A" & Rows.Count).End(xlUp).offset(1,0).EntireRow.Value = _
rCell.EntireRow.Value
Next rCell
Application.ScreenUpdating = True
End Sub