Find and activate a worksheet with VBA Excel - vba

I have an array of sheet names. I want to copy data from another file and paste the data in the respective worksheet. But it doesn't find the sheet. It creates an error in this step:
worksheets.(sheets(i)).Activate
Here is my code:
Sub NewWorkshet()
Dim criteria(40) As Integer
Dim i As Integer
Dim MyFile As String
MyFile = Application.GetOpenFilename()
criteria(0) = 335
criteria(1) = 336
criteria(2) = 337
criteria(3) = 338
criteria(4) = 339
criteria(5) = 351
criteria(6) = 392
criteria(7) = 393
Dim sheets As Variant
sheets = Array(a335, a336, a337, a338, a339, a351, a392, a393)
For i = 0 To 7
' Remove Filter
Windows("firstbook.xlsx").Activate
ActiveSheet.Range("$A$1:$S$6274").AutoFilter Field:=17
Workbooks.Open (MyFile)
Worksheets("first").Select
ActiveSheet.Range("$A$1:$O$3339").AutoFilter Field:=2, Criteria1:=criteria(i)
Range("A2").Select
Range(Selection, Selection.End(xlToRight)).Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Windows("firstbook").Activate
Worksheets("sheets(i)").Select
Range("B2").Select
Selection.End(xlDown).Select
Selection.Offset(1, -1).Select
ActiveSheet.Paste
Workbooks(MyFile).Close SaveChanges:=False
Next i
End Sub

Its treating Worksheets("sheets(i)").Select literally as a word sheets(i) not as a variable. So it wont change and it will not find your sheet.
You need to create a string for this.
Try add Dim MySheet As String
then use this in loop:
MySheet = "sheets(" & i & ")"
Then MySheet can be referenced and will change as you want.

Your issue is that you haven't set your 'sheets' values as text.
sheets = Array(a335, a336, a337, a338, a339, a351, a392, a393)
The code should read
Dim sheets(0 To 7) As Variant
sheets(0) = "a335"
sheets(1) = "a336"
sheets(2) = "a337"
sheets(3) = "a338"
sheets(4) = "a339"
sheets(5) = "a351"
sheets(6) = "a392"
sheets(7) = "a393"
Then refer as follows;
Worksheets(sheets(i)).Select

The issue is that
Worksheets("sheets(i)").Select
is looking for a worksheet called "sheets(i)" as a text/name.
If you use instead
Worksheets(sheets(i)).Select
then it is looking for a workhseet called like the value of the variable/array sheets(i)

Related

If statement in code to populate form

I have two sheets in a workbook. One contains a form, and the other contains data to populate the form with. I was able to write a small macro which successfully loops and populates the cell, Job Title, in Range("B16:I16") with the information in Column A from Data.
I'm trying to write an If statement within VBA that would populate the cell, Employee Work Location (Building), in Range("D14:H14") depending on the text in Job Title.
I wrote something out, but it doesn't seem to work. I get a mismatch error. May I ask for help with this please?
Thank you!
Sub FormPopulate_Click()
Dim i As Integer
Dim Building_Location as String
For i = 2 To 3
Sheets("Data").Select
Range("A" & CStr(i)).Select
ThisFile = Range("A" & CStr(i))
Selection.Copy
Sheets("Form").Select
Range("B16:I16").Select
ActiveSheet.Paste
Sheets("Form").Select
If Worksheets("Form").Range("B16:I16") = "Coordinator" Then
Building_Location = "East Quad"
Else
Building_Location =""
End If
Sheets("Form").Range("D14:H14").Value = Building_Location
Next i
End Sub
The main issue is you can't check multiple cells' values at once. You're trying this with ...Range("B16:I16") = "Coordinator". Instead, use something like COUNTIF().
Sub FormPopulate_Click()
Dim i As Long
Dim Building_Location As String
Dim dataWS As Worksheet, formWS As Worksheet
Dim thisFile As Range, destRange As Range
Set dataWS = Sheets("Data")
Set formWS = Sheets("Form")
For i = 2 To 3
Set thisFile = dataWS.Range("A" & i)
Set destRange = formWS.Range("B16:I16")
thisFile.Copy destRange
If WorksheetFunction.CountIf(formWS.Range("B16:I16"), "Coordinator") = destRange.Cells.Count Then
Building_Location = "East Quad"
Else
Building_Location = ""
End If
formWS.Range("D14:H14").Value = Building_Location
Next i
End Sub
Another note, you're going to overwrite the data in formWS.Range("B16:I16")in each iteration. Is that okay?
This part of the code:
Selection.Copy
Sheets("Form").Select
Range("B16:I16").Select
ActiveSheet.Paste
refers to cell data already copied, but here is being pasted to a range?? This is not (really) a range as it is a merged cell, so the reference should be B16 or B16:B16
Similarly later,
If Worksheets("Form").Range("B16:I16") = "Coordinator" Then ... should also only reference the single cell, as above.
Good luck.

Excel macro - check for a string in a cell, run a routine, move to the next row, do it again

I am not a Dev, but given I do use Excel, I have been tasked to create a looping macro that will check for a string ('Resource') in a cell and if it finds that string, then run a Copy and Paste code and then move to the next row. This starts at row 5 and runs continuously until row 199, but does not work on every row, hence the validation for the string Resource.
I have managed to create the macro for the Copy and Paste but it also has issues as I created it using the macro recorder and it only works on the row I actually did the recording on.
I am at a complete loss, can anyone help?
this is what I have so far
A New Resource name is added manually to the spreadsheet
the user clicks cell (C6) to focus the curser
the user clicks a macro button called 'Forecast for Future Project 1' to start the macro
On the button click the Macro will:
Interogate if cell to the left of current cell (B6) = 'Resource'
IF Yes, THEN
Sub CP()
DO
Range("C6").Select
Selection.Copy
Application.Goto Reference:="ProjAdd"
ActiveSheet.Paste
Application.CutCopyMode = False
ActiveCell.FormulaR1C1 = _
"=SUMIF('Current Project Utilisation'!R2C1:R62C1,RC1,'Current Project Utilisation'!R2C:R62C)+SUMIF('Future Project 1'!R2C1:R62C1,RC1,'Future Project 1'!R2C:R62C)"
Range("ProjAdd").Select
Selection.Copy
Range("C6").Select
ActiveSheet.Paste
Application.CutCopyMode = False
Selection.Copy
Range(Selection, Selection.End(xlToRight)).Select
ActiveSheet.Paste
Range("B6").Select
Loop Until ActiveCell.Address(0,0) = "$B$199"
End Sub
Move to cell under original active cell (C7) and Repeat the Macro until cell C199 is reached
If (B6) does not = 'Resource' then move to go to the cell under (C7) aand Repeat the Macro until cell C199 is reached
Refresh Worksheet to update data
Would something like this work for you?
Sub CopyPasteResource()
Dim CopyRange As Range
Dim Cell As Range
Set CopyRange = Workbooks("YourWorkBookName").Sheets("Sheet1").Range("C6:C199")
For Each Cell In CopyRange
If InStr(1, Cell.Offset(0, -1).Text, "Resource") Then
Cell.Copy
'paste where you wish
End If
Next Cell
End Sub
EDIT: Or do you want to loop through B6:B199 and then C6:199? I'm not entirely clear on the aim.
Ah the old macro recorder, generating 90% extra code since 1997. I couldn't exactly figure out from your question what exactly is being copied and to where but this code will loop through rows 5 to 199, check if the value in column B = "Resource" and then set the corresponding value in column C, you should be able to modify for your needs but I think you definitely want a structure more like this than what the recorder generated for you..
public sub cp()
Dim ws as Worksheet
Set ws = Worksheets("Current Project Utilisation")
Dim i as int
for iI = 5 to 199
if(ws.cells(i, 2).value = "Resource") then
ws.cells(i, 3).value = "what you're copying"
end if
next I
end sub
Assuming your cell range doesn't change you can do this for the looping part
Sub ResourceCheck()
Dim WS As Worksheet
Set WS = ActiveSheet
Dim Resources() As Long, r As Long
ReDim Resources(5 To 199)
For r = 5 To 199
If UCase(WS.Cells(r, 2).Value) = "RESOURCE" Then
WS.Cells(r, 3).Value = "x"
'Do copy paste part
End If
Next r
Application.Calculate
End Sub
Can you add a sample of your data? It's a bit hard to see what you're referencing to and how the data relates to each other.
Also, where is the "Projadd" cell reference? And what does it do?
Sub CP()
' I like to know what worksheet I'm on
Dim ws as Worksheet
' if it's a dedicated worksheet use this
' Set ws = ThisWorkbook.Worksheets("Sheet1")
' Otherwise following your current code
Set ws = ActiveSheet
' I also like to grab all my data at once
Dim Data as Variant
Data = ws.Range("B6:B199")
' No need to focus the cursor
For row = 5 to 199
' No need to select any range
' Is this case-sensitive???
If Data(row-4, 1) = "Resource" Then
' Copy C6??? Paste 'ProjAdd'
ws.Cells(row, 3).Copy Range("ProjAdd")
Application.CutCopyMode = False
End If
Next
End Sub

How to hide and copy a checkbox using vba

I have the base column with the checkbox, (the D column in my code), and i want to copy that column with the checbox to the other columns, but the column D must be hide(all the data including the checkbox).
the problem here is:
i don't know how to hide the checbox, when i hide the column the checbox still visible.
when i coppy the column the checbox in the colum does not be copied
This is the fuction that i actually used.
Private Sub cmdAddNewXref_Click()
Columns("D:D").Select
Selection.Copy
i = 3
Cells(2, i).Select
Do
i = i + 1
Loop While Cells(2, i) <> ""
Cells(2, i).Select
'MsgBox ActiveCell.Column
Columns(i - 1).Select
Columns("D:D").Select
Selection.Copy
Columns(i).Select
ActiveSheet.Paste
Selection.EntireColumn.Hidden = False
Application.CutCopyMode = False
Range("A1").Select
End Sub
but most importantly what i want to do, is possible?
EDIT 1: actually thanks to Scott Holtzman i can hide the checkbox with the columns.
Give this is a shot. There's probably a bit more of ideal way to do it, but I tested it and got it to work.
There are some assumptions on cell ranges and such that you will need to adjust to meet your exact spreadsheet specs.
Option Explicit
Private Sub cmdAddNewXref_Click()
Dim i As Integer
Dim ws As Worksheet
Set ws = Worksheets("mySheet") 'change as needed
'find next column to copy
i = 3
Do
i = i + 1
Loop While ws.Cells(2, i) <> ""
With ws.Columns("D:D")
.EntireColumn.Hidden = False
.Copy Columns(i)
End With
'copy checkbox in column D
Dim cb As Shape
Set cb = ws.Shapes("CheckBox1") 'change name as needed
cb.Copy
ws.Cells(4, i).Select 'assumes checkbox should be in row 4, change to wherever it is on column D for you
ws.Paste
ws.Columns("D:D").EntireColumn.Hidden = True
End Sub
CHange the paste, to paste special values, to hide the check its the .visible property I believe.
hope this helps.
From what I gathered... Copying the row, to somewhere else, but not the control, then he wanted to hide copied row. :)
Option Explicit
Sub test()
' From above code in yours I will be col number
Dim i As Integer
i = 5
Columns("A:A").Copy
Sheet2.Activate
ActiveSheet.Cells(1, i).PasteSpecial xlPasteValues
End Sub

How To Paste My Formula In A Cell With Specific Text Instead Of A Column?

I pretty much have an already working macro for me but for the future it may cause problems because the macro i have finds the column i gave it and then starts to input the formula there. Now my data may change in the future and in that column i might have something new so the macro would obviously run the formulas to the wrong column. Changing it manually is possible but hectic and a lot of work. Is there any possible way i can select a cell with a specific text in it instead of the column? since the text will never change this will me much easier for me to work with. Because doing this the formulas will always be posted in the correct column.
EDIT! I added the whole code to the post so you can see it more clearly and understand what i mean more clearly.
Sub HW_Copy_RawData_Formulas()
Dim intChoice As Integer
Dim strPath As String
Dim I As Integer
Dim filePath As String
Dim SourceWb As Workbook
Dim TargetWb As Workbook
Dim Lastrow As Long
Dim Nrow As Long
Set TargetWb = ActiveWorkbook
' Delete Rows
On Error Resume Next
TargetWb.Worksheets("Raw Data").Activate
Range("A2:AL2").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Delete Shift:=xlUp
Range("A2:AL2").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Delete Shift:=xlUp
'Copy Formulas
Range("AF2").Formula = "=IF([#ServDt]<DATE(2013,1,1), DATE(YEAR([#ServDt]),12,31),EOMONTH([#ServDt],0))"
Range("AG2").Formula = "=IF([#Amount]>1,[#Quantity],0)"
Range("AH2").Formula = "=IF([#Amount]<>0,[#Amount]-[#Adj]-[#[Adjustment ]],0)"
Range("AI2").Formula = "=IF(AND([#Department]=""HH"",[#Pay]=0),[#Amount]/2,0)"
Range("AJ2").Formula = "=IF([#Amount]<>0,[#Bal]-[#[Adjustment ]],[#Bal]+[#Adj])"
Range("AK2").Formula = "=VLOOKUP([Department],Service[#All],2,FALSE)"
Range("AL2").Formula = "=VLOOKUP([#Entity],Site,3,FALSE)"
MSG1 = MsgBox("Add Raw Data", vbYesNo)
If MSG1 = vbYes Then
'only allow the user to select one file
Application.FileDialog(msoFileDialogOpen).AllowMultiSelect = False
'make the file dialog visible to the user
intChoice = Application.FileDialog(msoFileDialogOpen).Show
'determine what choice the user made
If intChoice <> 0 Then
'get the file path selected by the user
strPath = Application.FileDialog( _
msoFileDialogOpen).SelectedItems(1)
Else: GoTo endmsg
End If
'Setting source of data
Set SourceWb = Workbooks.Open(strPath)
Lastrow = SourceWb.Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row
SourceWb.Worksheets(1).Range("A2:BJ" & Lastrow).SpecialCells(xlCellTypeVisible).Select
Selection.Copy Destination:=TargetWb.Sheets("Raw Data").Range("A2")
' Close the source workbook without saving changes.
SourceWb.Close savechanges:=False
Else
endmsg:
MsgBox "Complete"
End If
Range("AF2:AL2").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Range("AF2").PasteSpecial xlPasteValues
End Sub
The following code snippet might be of use to you. It acquires the range of the cell given a specific value. It can also be used to search a specific row with .Rows() instead.
Dim *YOURCELL* As Range
Set *YOURCELL*= .Columns(1).Find(What:= *WHATYOUWANTTOFIND*, LookAt:=xlWhole, MatchCase:=False, searchformat:=False)
If, however, you do not know where the last used cell is located, then consider reading this other post.
EDIT:
The while loop runs as long as the currently selected cell is not empty. In this loop, it selects the next cell to the right and increments a count. After the loop has finished, the currently selected cell is the first empty cell in the second row. Count has found the column number of it by incrementing alongside the loop, so it can then be used as needed. I used cells instead of range afterwards because it can use the column number.
Range("A2").Select
Dim count As Integer
count = 1
'skip all used cells in the row
Do While Not (ActiveCell.value = None)
ActiveCell.Offset(0, 1).Range("A1").Select
count = count + 1
Loop
Cells(count, 2).Formula = your_formula
Cells(count + 1, 2).Formula = your_formula ' next cell to the right
Cells(count + 2, 2).Formula = your_formula ' next cell to the right

How to define PIVOT table source dynamically?

I'm trying to do a PIVOT table from different worksheets and insert each PIVOT output in a certain column into a table.
Sub PivotvpcodeSATURATION()
Dim wsNew As Worksheet
Dim i As Integer
Dim z As Integer
Set ws1 = ActiveWorkbook.Sheets("24.11.")
Set ws2 = ActiveWorkbook.Sheets("25.11.")
Set ws3 = ActiveWorkbook.Sheets("26.11.")
Set ws4 = ActiveWorkbook.Sheets("27.11.")
Set ws5 = ActiveWorkbook.Sheets("28.11.")
Set ws6 = ActiveWorkbook.Sheets("29.11.")
Set ws7 = ActiveWorkbook.Sheets("30.11.")
Set wsNew = Sheets.Add
i = 3
z = 16
Do
ws1.Select
Range("A2").Select
ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
"24.11.!R1C2:R11754C10", Version:=xlPivotTableVersion14).CreatePivotTable _
TableDestination:=wsNew.Name & "!R3C1", TableName:="PivotTable", DefaultVersion _
:=xlPivotTableVersion14
wsNew.Select
Cells(3, 1).Select
With ActiveSheet.PivotTables("PivotTable").PivotFields("VP CODE")
.Orientation = xlRowField
.Position = 1
End With
wsNew.Select
ActiveSheet.PivotTables("PivotTable").AddDataField ActiveSheet.PivotTables( _
"PivotTable").PivotFields("1/0"), "Sum of 1/0", xlSum
wsNew.Select
Range("B4").Select
Range(Selection, Selection.End(xlDown)).Select
Selection.Copy
Sheets("VP_Saturation").Select
' Range(Cells(3, z).Address).Select
ActiveSheet.Paste
Application.DisplayAlerts = False
wsNew.Delete
Application.DisplayAlerts = True
z = z + 2
Loop Until z = 28
End Sub
The thing i am non able to reach is,
how to define a worksheets name as a variable, so that i don't have to select w1, w2,w.., wn each time, and don't have to put a sheet name inside 24.11.!R1C2:R11754C10 .
As well the column name where to insert copied Pivot result i define as a variable Cells(3, z).Address.Select, but this string returns an error.
Maybe someone can help with it? Thanks!
put all worksheets in an array and do a cycle on each element of the array with For Each....Next
regarding your second question, change:
SourceData:="24.11.!R1C2:R11754C10"
to
SourceData:=ws1.name&"!R1C2:R11754C10"
and it will feed the worksheet name into the string
third question:
replace
Range(Cells(3, z).Address).Select
with
Cells(3, z).Select
If you use a template Excel file where the format doesn't change. I suggest creating a dynamic named range for all your data sources. Then just go to each pivot table and refer to the named range in Change Source Pivot Table Options.
All your VBA has to do is a variation of ThisWorkbook.RefreshAll.
Use a variation of this formula to create the dynamic named range: =Data!$A$5:OFFSET(Data!$A$5,COUNTA(Data!$A:$A)-1,52). Basically choose the data source sheet, the starting cell, and how many columns over the data sits. The rows will adjust automatically.