If statement in code to populate form - vba

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.

Related

I need help looping an index/match that is inside an if statement using Excel VBA

I am trying to create a VBA macro to fill in cells that are empty in a range ("INV_Nums") without overwriting the cell if it contains data already. In order to accomplish this I am trying to use an if statement to check if the cell in question is blank...if it is not, then I want the loop to continue on to the next cell, however if it IS blank then I want to input the index(__,(match()) function into the cell.
I keep getting a "compile error: mismatch" on the True statement but I'm at a loss as to why my synatax would be wrong. Any help would be appreciated.
Here is my code:
Dim i As Integer
Dim Rng As Range
Dim ARwkb As Excel.Workbook
Dim ARwks As Excel.Worksheet
Dim Samwkb As Excel.Workbook
Dim Samwks As Excel.Worksheet
Set Samwkb = Excel.Workbooks("Samples - one sheet")
Set Samwks = Samwkb.Worksheets("samples shipment")
Set ARwkb = Excel.Workbooks("AR balance.xlsx")
Set ARwks = ARwkb.Worksheets("Total Trading")
Set Rng = Samwkb.Range("INV_Nums")
For i = 6 To Rng.Rows.Count + 6
If Range("AAi") = "" Is True Then
Range("AAi").Select
ActiveCell.FormulaR1C1 = _
"=INDEX('AR balance.xlsx'!AR_Invoice_Nums,MATCH(RC[-21],'AR
balance.xlsx'!AR_PL_Nums,0))"
End If
Next i
The problem is in how you are identifying the range and administering the criteria.
For i = 6 To Rng.Rows.Count + 6
If IsEmpty(Range("AA" & i)) Then
Range("AA" & i).FormulaR1C1 = _
"=INDEX('AR balance.xlsx'!AR_Invoice_Nums, MATCH(RC[-21],'AR balance.xlsx'!AR_PL_Nums, 0))"
End If
Next i
The .SpecialCells method can quickly determine the blank cells and an xlR1C1 formula can be used to insert all of the formulas at once..
...
with Samwkb.Range("INV_Nums")
.specialcells(xlcelltypeblanks).FormulaR1C1 = _
"=INDEX('AR balance.xlsx'!AR_Invoice_Nums, MATCH(RC[-21],'AR balance.xlsx'!AR_PL_Nums, 0))"
end with
...

Error by copy pasting ranged due to merged cells

SOLVED, SEE CODE BELOW
I'm working on a code for filtering data and pasting the filtered data to the "destination" sheet.
In the "review" sheet there is a long list with data that can be subdivided in certain categories. In cell F9 off the coversheet I can select a category.
After pressing a button the data in the "review" sheet needs to be filtered and the data that is left after filtering should be pasted in the "destination" sheet. the "destination" sheet is a blank new sheet.
The filtering part works, however the copy paste part is giving some errors. Because the "review" sheet has some merged cells in it. I am able to paste the formatting and the columnwidths, but the values give an error due to merged cells. Is there some way to work around this??
In addition to this, when pasting the formatting, this is pasted to the same number of rows as in the "review" sheet before filtering. I want the formatting to be applicable on only the numer of rows left after filtering.
I hope someone can help me out.
See my source code below:
Dim wksCVP As Worksheet
Dim wksReview As Worksheet
Dim wksNew As Worksheet
Set wksReview = Worksheets("REVIEW")
Set wksCVP = Worksheets("COVER PAGE")
Set wksNew = ThisWorkbook.Worksheets.Add
wksReview.Cells.Copy wksNew.Cells
wksNew.Cells.UnMerge
Dim LastRow As Long
With wksNew
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
Select Case wksCVP.Range("F9").Value
Case "Instrumentation"
kolom = "J"
Case "Equipment"
kolom = "K"
Case "Design / Fabrication"
kolom = "L"
Case "Inspection & Testing"
kolom = "M"
Case "General / Other"
kolom = "N"
End Select
If wksCVP.Range("F9").Value <> "" Then
For i = 5 To LastRow
If wksNew.Range(kolom & i).Value <> "X" Then
wksNew.Rows(i).EntireRow.Hidden = True
End If
Next i
End If
wksNew.Activate
ActiveSheet.Range("A5", "Z" & LastRow + 1).SpecialCells(xlCellTypeVisible).Copy
With Sheets("DESTINATION").Range("A1")
.PasteSpecial Paste:=xlPasteAll
End With
wksNew.delete
For the Formats and the ColumnWidths being in a merged cell, which is only partially copied, the easiest way is to add a new worksheet, to copy the initial values there and to unmerge it. Then do something like this:
Option Explicit
Sub TestMe()
Dim wksTheNew As Worksheet
Dim wksReview As Worksheet
Dim wksDestination As Worksheet
Set wksReview = Worksheets("Review")
Set wksDestination = Worksheets("Destination")
Set wksTheNew = ThisWorkbook.Worksheets.Add
wksReview.Cells.Copy wksTheNew.Cells
wksTheNew.Cells.UnMerge
'now copy the formats and the values from wksTheNew
'it will not give an error, because it is unmerged
Application.DisplayAlerts = False
wksTheNew.Delete
Application.DisplayAlerts = True
End Sub
Once you are ready with your actions, you may simply delete the new worksheet.
Just change your sequence:
With Sheets("DESTINATION").Range("A1")
.PasteSpecial Paste:=xlPasteValues
.PasteSpecial Paste:=xlPasteFormats
.PasteSpecial Paste:=xlPasteColumnWidths
End With
Pasting values first shouldn't trigger an error.

Excel: Click button to copy row onto another worksheet

I know, I know. There are a ton of suggestions how to solve that particular problem, but somehow they all tend to fail with me.
What I have (simplified): A (Mac) Excel-Sheet "Output" with:
Name Time Date
Mike 08:00 01.01.2016
The second row is yielding the data based on some input on yet another sheet.
What I need:
Whenever I will change the second row of "Output" (i.e. changing the input), I can click a button to add the entire second row onto a new worksheet "Log" (that will feature a header as well). Essentially logging the data upon clicking the button. The data can only be added once, multiple entries of the same data are deleted. After logging the data in "Log", the second row of "Output" does not need to be cleared, however I should not be able to add the same data again.
Any thoughts?
*EDIT
I modified the code from here: http://goo.gl/48jjDo.
Sub Submit()
Application.ScreenUpdating = False
Dim refTable As Variant, trans As Variant
refTable = Array("A = A2", "B = B2", "C=C2")
Dim Row As Long
Row = Worksheets("Log").UsedRange.Rows.Count + 1
For Each trans In refTable
Dim Dest As String, Field As String
Dest = Trim(Left(trans, InStr(1, trans, "=") - 1)) & Row
Field = Trim(Right(trans, Len(trans) - InStr(1, trans, "=")))
Worksheets("Log").Range(Dest).value = Worksheets("Output").Range(Field).value
Next
Application.ScreenUpdating = True
End Sub
*Edit2
Ok this got me further:
Sub CopyRangeFromSheet1toSheet2()
Dim lastRow As Long
lastRow = Sheets("Sheet2").Range("A100000").End(xlUp).Row + 1 ' then next free row in sheet2
Sheets("Sheet1").Range("A2:C2").Copy Destination:=Sheets("Sheet2").Range("A" & lastRow)
End Sub
However, how do I check now for multiple data? And I will need to paste only the values.
So far this works:
Sub CopyFormulas()
Dim sht1 As Worksheet, sht2 As Worksheet
Set sht1 = Sheets("Output")
Set sht2 = Sheets("Log")
sht1.Range("A2:C2").Copy
sht2.Cells(Rows.Count, "A").End(xlUp).Offset(1, 0).PasteSpecial xlPasteValues
Application.CutCopyMode = False
response = MsgBox("data was added")
End Sub
Not it is only the check for multiple entries that is missing

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

Copy/Paste Specific Columns from a Worksheet to another

I want to copy some columns with headers from a worksheet to another one. I've created an array that looks for the different headers needed so I can copy and paste the entire column into the new tab. I know I have an error somewhere because I'm getting a type mismatch error and possibly other types as well. Can someone take a look and see what I'm missing/have wrong?
Dim rngCell As Range
Dim strHeader() As String
Dim intColumnsMax As Integer
Sheets.Add.Name = "Material Master"
Sheets.Add.Name = "BOM"
intColumnsMax = Sheets("HW Zpure Template").UsedRange.Columns.Count
ReDim strHeader(1 To intColumnsMax)
strHeader(1) = "MATERIAL"
strHeader(2) = "MATERIAL TYPE"
strHeader(3) = "MATERIAL DESCRIPTION"
For Each rngCell In Rows(4)
For i = 1 To intColumnsMax
If strHeader(i) = rngCell.Value Then
rngCell.EntireColumn.Copy
Sheets("Material Master").Select
ActiveSheet.Paste Destination:=Worksheets("Material Master").Cells(1, i)
Sheets("HW Zpure Template").Select
End If
Next i
Next
I prefer to use Application.Match to locate a specific column header label rather than cycling through them trying to find a match. To that end, I've heavily modified your code.
Dim c As Long, v As Long, vHDRs As Variant
Dim s As Long, vNWSs As Variant, wsMM As Worksheet
vHDRs = Array("MATERIAL", "MATERIAL TYPE", "MATERIAL DESCRIPTION")
vNWSs = Array("Material Master", "BOM")
For v = LBound(vNWSs) To UBound(vNWSs)
For s = 1 To Sheets.Count
If Sheets(s).Name = vNWSs(v) Then
Application.DisplayAlerts = False
Sheets(s).Delete
Application.DisplayAlerts = True
Exit For
End If
Next s
Sheets.Add after:=Sheets(Sheets.Count)
Sheets(Sheets.Count).Name = vNWSs(v)
Next v
Set wsMM = Sheets("Material Master")
With Sheets("HW Zpure Template")
For v = LBound(vHDRs) To UBound(vHDRs)
If CBool(Application.CountIf(.Rows(4), vHDRs(v))) Then
c = Application.Match(vHDRs(v), .Rows(4), 0)
Intersect(.UsedRange, .Columns(c)).Copy _
Destination:=wsMM.Cells(1, Application.CountA(wsMM.Rows(1)) + 1)
End If
Next v
End With
Set wsMM = Nothing
Correct me if I'm wrong, but your code seemed to be looking for the column labels in row 4. That is what I'm using above but if that assumption is incorrect then the fix should be fairly self-evident. I've also stacked the copied columns into the first available column to the right. Your code may have been putting them in the original position.
When you run the above, please note that it will remove worksheets named Material Master or BOM without asking in favor of inserting its own worksheets of those names. Given that, it's probably best to run on a copy of your original.
Using the Find() method is a very efficient way of finding the data you want. Below are a few suggestions to optimize your existing code.
Dim rngCell As Range
Dim strHeader() As String
Dim intColumnsMax As Integer
Dim i As Integer
Sheets.Add.Name = "Material Master"
Sheets.Add.Name = "BOM"
'Quick way to load a string array
'This example splits a comma delimited string.
'If your headers contain commas, replace the commas in the next line of code
'with a character that does not exist in the headers.
strHeader = Split("MATERIAL,MATERIAL TYPE,MATERIAL DESCRIPTION", ",")
'Only loop through the headers needed
For i = LBound(strHeader) To UBound(strHeader)
Set rngCell = Sheets("HW Zpure Template").UsedRange.Find(What:=strheader(i), LookAt:=xlWhole)
If Not rngCell Is Nothing Then
'Taking the intersection of the used range and the entire desired column avoids
'copying a lot of unnecessary cells.
Set rngCell = Intersect(Sheets("HW Zpure Template").UsedRange, rngCell.EntireColumn)
'This method is more memory consuming, but necessary if you need to copy all formatting
rngCell.Copy Destination:=Worksheets("Material Master").Range(rngCell.Address)
'This method is the most efficient if you only need to copy the values
Worksheets("Material Master").Range(rngCell.Address).Value = rngCell.Value
End If
Next i