VBA: Subs do nothing unless file was manually opened - excel

I have the following Macro:
Sub Remove_Junk_Data()
Call Open_Workbook
Call Scrub_Master
Call Scrub_Change_History
Call Scrub_Update
Call Scrub_ExistingOwnership
Call Save_Scrubbed
End Sub
Sub Open_Workbook()
Workbooks.Open "https://company.sharepoint.com/sites/project/subproject/subsubproject/subsubprojecttool/tooloutput/tooloutput.xlsx"
Workbooks("tooloutput.xlsx").Activate
End Sub
Sub Scrub_Master()
Dim myValue As String
Dim LastRow As Long
Dim i As Long
Dim r As Range
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
myValue = ""
Sheets("Master").Select
For i = LastRow To 1 Step -1
Set r = Cells(i, 1)
If r.Value = myValue Then r.EntireRow.Delete
Next i
End Sub
Sub Scrub_Change_History()
Dim myValue As String
Dim LastRow As Long
Dim i As Long
Dim r As Range
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
myValue = ""
Sheets("Change History").Select
For i = LastRow To 1 Step -1
Set r = Cells(i, 1)
If r.Value = myValue Then r.EntireRow.Delete
Next i
End Sub
Sub Scrub_Update()
Dim myValue As String
Dim LastRow As Long
Dim i As Long
Dim r As Range
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
myValue = ""
Sheets("Update").Select
For i = LastRow To 1 Step -1
Set r = Cells(i, 1)
If r.Value = myValue Then r.EntireRow.Delete
Next i
End Sub
Sub Scrub_ExistingOwnership()
Dim myValue As String
Dim LastRow As Long
Dim i As Long
Dim r As Range
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
myValue = ""
Sheets("ExistingOwnership").Select
For i = LastRow To 1 Step -1
Set r = Cells(i, 1)
If r.Value = myValue Then r.EntireRow.Delete
Next i
End Sub
Sub Save_Scrubbed()
Application.DisplayAlerts = False
ActiveWorkbook.SaveAs Filename:= _
"https://company.sharepoint.com/sites/project/subproject/subsubproject/subsubprojecttool/tooloutput/tooloutput.xlsx", _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
Application.DisplayAlerts = False
Workbooks("Master_FM_Update.xlsx").Close
End Sub
If I comment out the "Open_Workbook" sub and manually open the workbook then run the remainder of Remove_Junk_Data(), it works perfectly.
If I try to run Remove_Junk_Data with Open_Workbook active, then no errors are thrown, but the 4 middle subs dont do anything...
Has anyone ran into anything like this? Did you find a resolution? I want to click a button and have all 6 subs do their thing correctly...
Edit: With input, new macro, and it works! Thanks guys!:
Sub Remove_Junk_Data()
Workbooks.Open "https://company.sharepoint.com/sites/project/subproject/subsubproject/Subsubprojecttool/tooloutput/tooloutput.xlsx"
Dim myValue As String
Dim LastRow As Long
Dim i As Long
Dim r As Range
With Workbooks("tooloutput.xlsx").Sheets("Master")
LastRow = .Cells(Rows.Count, "A").End(xlUp).Row
myValue = ""
For i = LastRow To 1 Step -1
Set r = .Cells(i, 1)
If r.Value = myValue Then r.EntireRow.Delete
Next i
End With
With Workbooks("tooloutput.xlsx").Sheets("Change History")
LastRow = .Cells(Rows.Count, "A").End(xlUp).Row
myValue = ""
For i = LastRow To 1 Step -1
Set r = .Cells(i, 1)
If r.Value = myValue Then r.EntireRow.Delete
Next i
End With
With Workbooks("tooloutput.xlsx").Sheets("Update")
LastRow = .Cells(Rows.Count, "A").End(xlUp).Row
myValue = ""
For i = LastRow To 1 Step -1
Set r = .Cells(i, 1)
If r.Value = myValue Then r.EntireRow.Delete
Next i
End With
With Workbooks("tooloutput.xlsx").Sheets("ExistingOwnership")
LastRow = .Cells(Rows.Count, "A").End(xlUp).Row
myValue = ""
For i = LastRow To 1 Step -1
Set r = .Cells(i, 1)
If r.Value = myValue Then r.EntireRow.Delete
Next i
End With
End Sub

I have done some changes to your code, the comments in the procedure intent to explain the changes. My advice is that besides what you are getting from sites like Stackoverflow you should also read the corresponding documentation to achieve a deeper understanding of the concepts and resources used. Nevertheless, do not hesitate to ask question as you go forward in developing your programing skills.
The code below consolidates all what you are trying to do in one procedure, there you'll see how to run repetitive code for a series of values (i.e. worksheets in this case)
Suggest to visit the following pages:
Variables & Constants, Application Object (Excel), Excel Objects
With Statement, For...Next Statement, For Each...Next Statement,
If...Then...Else Statement
Worksheets Object (Excel), Worksheet Object (Excel), Range Object (Excel)
Sub Remove_Junk_Data()
Rem Use an Array Variable to List all the worksheets you want to work with
Dim aWsh As Variant, vItm As Variant
aWsh = Array("Master", "Change History", "Update", "ExistingOwnership")
Rem Declare Object Variables
Dim Wbk As Workbook
Dim Wsh As Worksheet
Dim lRowLst As Long
Dim lRow As Long
Rem Open Workbook & Set Workbook Object Variable
Set Wbk = Workbooks.Open("https://company.sharepoint.com/sites/project/subproject/subsubproject/subsubprojecttool/tooloutput/tooloutput.xlsx")
Rem Loop throught the worksheet list and process each one
For Each vItm In aWsh
Rem Set Worksheet Object Variable
Set Wsh = Wbk.Worksheets(vItm)
With Wsh
lRowLst = Cells(Rows.Count, "A").End(xlUp).Row
For lRow = lRowLst To 1 Step -1
With .Cells(lRow, 1)
If .Value2 = Empty And Not (.HasFormula) Then .EntireRow.Delete
End With: Next: End With: Next
Application.DisplayAlerts = False
Wbk.Save
Application.DisplayAlerts = True
Workbooks("Master_FM_Update.xlsx").Close
End Sub

Related

Selecting specific column in a macro excel sheet

I have been using the code (code show below) suggested by PeterT in this public question
This macro works well if the data are in the first, second and third column like this of the sheet like this:
But now I have a more large spreadsheet and I would like to do the same but having one column and the other not immediately adjacent like this.
What modification do I need to do in the code to be able to do this.
Option Explicit
Sub testme()
FindValues "Profile"
End Sub
Sub FindValues(ByVal value As String)
Dim srcWB As Workbook
Dim srcWS As Worksheet
Set srcWB = ThisWorkbook
Set srcWS = srcWB.Sheets("Sheet1")
Dim dstWB As Workbook
Dim dstWS As Worksheet
Set dstWB = ThisWorkbook '--- change to the new workbook
Set dstWS = dstWB.Sheets("Sheet2")
'--- find the end of the data in the destination sheet
Dim dstRow As Long
With dstWS
dstRow = .Cells(.Cells.Rows.Count, 1).End(xlUp).Row
End With
With srcWS
Dim lastRow As Long
lastRow = .Cells(.Cells.Rows.Count, 1).End(xlUp).Row
Dim i As Long
For i = 1 To lastRow
If IsInMyList(.Cells(i, 1).value) Then
dstRow = dstRow + 1
dstWS.Cells(dstRow, 1).value = .Cells(i, 1).value
dstWS.Cells(dstRow, 2).value = .Cells(i, 2).value & "_" & .Cells(i, 3).value
End If
Next i
End With
End Sub
Function IsInMyList(ByVal value As String) As Boolean
Dim theList() As String
theList = Split("Albinism and nystagmus 31-gene panel,TAAD 27-gene panel (R125),PCD 29-gene panel", ",")
Dim item As Variant
For Each item In theList
If item = value Then
IsInMyList = True
Exit Function
End If
Next item
IsInMyList = False
End Function
I have tried by changing the selection of the column where I think the code does that but I dont get non a error neither the desired results
For i = 1 To lastRow
If IsInMyList(.Cells(i, 2).value) Then
dstRow = dstRow + 1
dstWS.Cells(dstRow, 2).value = .Cells(i, 2).value
dstWS.Cells(dstRow, 4).value = .Cells(i, 4).value & "_" & .Cells(i, 7).value
Non-Adjacent Columns
This is easily achieved by adding a string (srcColsList) containing the columns, writing the columns to an array (srcCols), and using the elements of the array as column 'identifiers', e.g. srcCols(0).
You are not using the parameter Profile passed to your sub, so I removed it.
Modify the A,F,D to fit your needs.
Option Explicit
Sub testme()
FindValues
End Sub
Sub FindValues()
Const srcColsList As String = "A,F,D" ' no spaces!
Dim srcCols() As String: srcCols = Split(srcColsList, ",")
Dim srcWB As Workbook: Set srcWB = ThisWorkbook
Dim srcWS As Worksheet: Set srcWS = srcWB.Sheets("Sheet1")
Dim dstWB As Workbook: Set dstWB = ThisWorkbook
Dim dstWS As Worksheet: Set dstWS = dstWB.Sheets("Sheet2")
'--- find the end of the data in the destination sheet
Dim dstRow As Long
With dstWS
dstRow = .Cells(.Cells.Rows.Count, 1).End(xlUp).Row
End With
With srcWS
Dim lastRow As Long
lastRow = .Cells(.Cells.Rows.Count, srcCols(0)).End(xlUp).Row
Dim i As Long
For i = 1 To lastRow
If IsInMyList(.Cells(i, srcCols(0)).Value) Then
dstRow = dstRow + 1
dstWS.Cells(dstRow, 1).Value = .Cells(i, srcCols(0)).Value
dstWS.Cells(dstRow, 2).Value = .Cells(i, srcCols(1)).Value _
& "_" & .Cells(i, srcCols(2)).Value
End If
Next i
End With
End Sub
Function IsInMyList(ByVal SearchString As String) As Boolean
Const StringList As String _
= "Albinism and nystagmus 31-gene panel," _
& "TAAD 27-gene panel (R125)," _
& "PCD 29-gene panel" ' no spaces!
IsInMyList = IsNumeric(Application _
.Match(SearchString, Split(StringList, ","), 0))
End Function

How to return cell value with For Next loop using 2 sheets and multiple conditions - VBA

I'm attempting to match values between two sheets and if found and the conditions are met, perform the action of changing the cell colour.
PROBLEM:
I'm getting an error with my For...Next loop, even though I thought I have a NEXT for each FOR statement. Not sure what I've done wrong.
Also, I'm not sure my counters are setup correctly to accurately scan through each sheet/column needed. Any help would be appreciated.
Sub ReadData()
Dim wb As Workbook
Dim ws As Worksheet
Dim lastrow As Long
Dim i As Long
Set wb = ActiveWorkbook
Set ws = wb.Sheets("Ref1")
Set ws2 = wb.Sheets("TRA")
lastrow = Sheets("Ref1").Cells(Rows.Count, "A").End(xlUp).Row
lastrow2 = Sheets("TRA").Cells(Rows.Count, "A").End(xlUp).Row
Sheets("Ref1").Activate
i = 2
k = 2
For i = 2 To lastrow
For k = 2 To lastrow2
If Cells(i, 4).Value = "Active" Then
If ws.Cells(i, 18).Value = ws2.Cells(i, 1).Value And (ws2.Cells(i, 23).Value <> "Cancelled" Or ws2.Cells(i, 23).Value <> "Completed") Then
Cells(i, 20).Interior.ColorIndex = 9
End If
Next
Next
End Sub
Quick Repair
To better understand the code, it is often preferable to use letters,
instead of numbers, for columns.
The Code
Sub ReadData()
Dim wb As Workbook
Dim ws As Worksheet
Dim ws2 As Worksheet
Dim lastrow As Long
Dim lastrow2 As Long
Dim i As Long
Dim k As Long
' Use ThisWorkbook instead of ActiveWorkbook, if the code is
' in the same workbook where these sheets are.
With ActiveWorkbook
Set ws = .Worksheets("Ref1")
Set ws2 = .Worksheets("TRA")
End With
lastrow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
lastrow2 = ws2.Cells(ws2.Rows.Count, "A").End(xlUp).Row
For i = 2 To lastrow
If ws.Cells(i, "D").Value = "Active" Then
For k = 2 To lastrow2
If ws.Cells(i, "R").Value = ws2.Cells(k, "A").Value _
And ws2.Cells(k, "W").Value <> "Cancelled" _
And ws2.Cells(k, "W").Value <> "Completed" Then
ws.Cells(i, "T").Interior.ColorIndex = 9 ' Brown
Exit For
End If
Next
End If
Next
End Sub

VBA Macro - Loop and get value then ovewrite the desired cell

I created a loop that will get the value of one cell to another cell under the same sheet.
The expected result should be this, if the loop runs it will get the 1st value then run my created procedure
next overwrite the same cell get the 2nd value then execute again my created procedure then get 3rd value .. overwrite the cell ..exec proc and so on ...
But my codes only get the last value of the selection.
Public Sub SpecNum()
Dim lrow As Long
Range("A2").Select
lrow = Selection.End(xlDown).Row
For x = 2 To lrow
Range("C2").Value2 = Cells(x, 1).Value2
Next x
Number
End Sub
Public Sub Number()
Dim SpecNum, pref, lastCell As String
Dim lrow As Long
SpecNum = Range("C2").Value2
For x = 2 To 6
Worksheets("Sheet3").Select
pref = Cells(x, "E").Value2
Cells(x, "C").Value2 = SpecNum & pref
Range("C2", Range("C2").End(xlToRight).End(xlDown)).Copy
Next x
Worksheets("Sheet1").Select
Range("A250").Select
Selection.End(xlUp).Select
ActiveCell.Offset(1, 0).Select
ActiveSheet.Paste
End Sub
output when moving the number inside the loop.. it doubled/tripled the values
expected result:
I refactored your code a bit. First of all - you should learn how to avoid using Selections (How to avoid using Select in Excel VBA).
Code without Selections is more flexible and less confusing.
Hope it works as you wanted:
Option Explicit
Public Sub SpecNum()
Dim lrow As Long
Dim x As Long
Dim wb As Workbook
Dim ws As Worksheet
Set wb = ThisWorkbook
Set ws = wb.Worksheets("Sheet3")
lrow = ws.Range("A2").End(xlDown).row
For x = 2 To lrow
ws.Range("C2").Value2 = ws.Cells(x, 1).Value2
Number
Next x
End Sub
Public Sub Number()
Dim SpecNum As String
Dim pref As String
Dim lrow As Long
Dim x As Long
Dim wb As Workbook
Dim ws3 As Worksheet
Dim ws1 As Worksheet
Set wb = ThisWorkbook
Set ws1 = wb.Worksheets("Sheet1")
Set ws3 = wb.Worksheets("Sheet3")
SpecNum = ws3.Range("C2").Value2
For x = 2 To 6
pref = ws3.Cells(x, "E").Value2
ws3.Cells(x, "C").Value2 = SpecNum & pref
Next x
ws3.Range("C2", ws3.Range("C2").End(xlToRight).End(xlDown)).Copy
ws1.Range("A250").End(xlUp).Offset(1, 0).PasteSpecial
End Sub
modified your loop structures. May try
Public Sub SpecNum()
Dim lrow As Long
Range("A2").Select
lrow = Selection.End(xlDown).Row
For X = 2 To lrow
Range("C2").Value2 = Cells(X, 1).Value2
Number
Next X
End Sub
Public Sub Number()
Dim SpecNum, pref, lastCell As String
Dim lrow As Long
SpecNum = Range("C2").Value2
For X = 2 To 6
Worksheets("Sheet3").Select
pref = Cells(X, "E").Value2
Cells(X, "C").Value2 = SpecNum & pref
'Range("C2", Range("C2").End(xlToRight).End(xlDown)).Copy
Range("C" & X, Range("C" & X).End(xlToRight)).Copy
Worksheets("Sheet1").Select
Range("A15").End(xlDown).End(xlDown).End(xlUp).Select
ActiveCell.Offset(1, 0).Select
ActiveSheet.Paste
Next X
End Sub
Or may please opt for simplified solution in single procedure
Public Sub SpecNum2()
Dim lrow As Long
Worksheets("Sheet1").Range("A2").Select
lrow = Selection.End(xlDown).Row
TrgRw = 15
For X = 2 To lrow
NumX = Worksheets("Sheet1").Cells(X, 1).Value2
For Y = 2 To 6
TrgRw = TrgRw + 1
Worksheets("Sheet3").Select
pref = Cells(Y, "E").Value2
Cells(Y, "C").Value2 = NumX & pref
'Range("C2", Range("C2").End(xlToRight).End(xlDown)).Copy
Range("C" & Y, Range("C" & Y).End(xlToRight)).Copy
Worksheets("Sheet1").Select
Range("A" & TrgRw).Select
ActiveSheet.Paste
Next Y
Next X
End Sub
Hope It will work

VBA code to Insert a Column

I want to insert a column to the right if string"P018" is present in the third row of the sheet:
My code is :
Sub Insrt()
Dim Found As Range
Dim LR As Long
Dim I As Integer
I = 1
Do While Cells(4, I).Value <> ""
'If Cells(3, I).Value = "P018" Then
Set Found = Cells(3, I).Find(what:="P018", LookIn:=xlValues, lookat:=xlWhole)
If Found Is Nothing Then GoTo Label
Found.Offset(, 1).EntireColumn.Insert
Label:
Loop
End Sub
This going in an endless loop.
You want to use a standard for loop that loops backwards:
Sub insert()
Dim ws As Worksheet
Dim lastColumn As Long
Dim i As Long
Set ws = ActiveSheet
With ws
lastColumn = .Cells(4, .Columns.Count).End(xlToLeft).Column
For i = lastColumn To 1 Step -1
If .Cells(3, i) = "P018" Then Columns(i + 1).insert
Next i
End With
End Sub

Copying rows from one sheet to another

The following script seems like it should work, but I'm getting an "Object defined" error on the lines marked below. I can't find what's causing this at all...
Sub MailMerge()
Sheets.Add.Name = "MailMerge"
Dim MailMerge As Worksheet
Set MailMerge = Sheets("MailMerge")
Dim Rng As Range
Dim i, index, lastrow As Long
Dim Abstracts As Worksheet
Set Abstracts = Sheets("Abstracts")
lastrow = Abstracts.Cells(Rows.Count, 1).End(xlUp).row
For i = 1 To lastrow
Set Rng = Abstracts.Range("O" & i)
If WorksheetFunction.CountA(Rng) >= 1 Then
Abstracts.Range("A" & i).Resize(0, 14).Copy _
Destination:=MailMerge.Range("A" & i).Resize(0, 14)
'this is where the error is occuring
End If
Next
End Sub
Any suggestions?
Resize is not like OFFSET. It will set the size of the range to the size dictated. So you are setting the range size to 0 rows. It should be 1:
Sub MailMerge()
Sheets.Add.Name = "MailMerge"
Dim MailMerge As Worksheet
Set MailMerge = Sheets("MailMerge")
Dim Rng As Range
Dim i, index, lastrow As Long
Dim Abstracts As Worksheet
Set Abstracts = Sheets("Abstracts")
lastrow = Abstracts.Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To lastrow
Set Rng = Abstracts.Range("O" & i)
If WorksheetFunction.CountA(Rng) >= 1 Then
Abstracts.Range("A" & i).Resize(1, 14).Copy _
Destination:=MailMerge.Range("A" & i).Resize(1, 14)
'this is where the error is occuring
End If
Next
End Sub

Resources