Macro Confusion [duplicate] - excel

This question already has answers here:
Excel VBA, getting range from an inactive sheet
(3 answers)
Closed 1 year ago.
In Excel VBA we have a spreadsheet which stores information and have one of each of our sites. The workbooks are identical but each contains info for a specific sites. These are in constant use and we have too many users to use a single book.
Since an update to office 365, if a user has more than one sheet open then the scripts are writing the data to the wrong sheet. The scripts are contained in a module and it appears that excel, on rare occasions runs the script (of the same name) from the wrong workbook.
Is there a simple way to make the code only run in the workbook it is contained in?
One thought was if we put it in the "this workbook" container rather than in a module might have this effect.
The spreadsheet is very long but in essence this is what it does:
Private Sub cmdSave_Click()
Set ws = Sheets("Repairs Log")
lr = ws.Cells(Rows.Count, 1).End(xlUp).Row + 1
ws.Cells(lr, 3).Value = txtsite
ws.Cells(lr, 4).Value = lbxblock
ws.Cells(lr, 5).Value = txtflat
ws.Cells(lr, 6).Value = txtroom
ws.Cells(lr, 7).Value = txtdescription
ws.Cells(lr, 9).Value = lbxtype
ws.Cells(lr, 8).Value = lbxassigned.Text
End Sub
Any ideas

ThisWorkbook
ThisWorkbook on Microsoft Docs
Option Explicit
' Being Careless
Sub AWB()
Dim wb As Workbook: Set wb = ActiveWorkbook ' workbook you are looking at
' Several possibilities: could be the wrong one!
' continue...
End Sub
' Memorize this.
Sub TWB()
Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
' One possibility: can't be the wrong one!
Dim ws As Worksheet: Set ws = wb.Worksheets("Repairs Log")
' continue...
End Sub
' Since it is simple enough, you can use the 'With' statemnt:
Private Sub cmdSave_Click()
With ThisWorkbook.Worksheets("Repairs Log")
Dim lr As Long: lr = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
.Cells(lr, 3).Value = txtsite
.Cells(lr, 4).Value = lbxblock
.Cells(lr, 5).Value = txtflat
.Cells(lr, 6).Value = txtroom
.Cells(lr, 7).Value = txtdescription
.Cells(lr, 9).Value = lbxtype
.Cells(lr, 8).Value = lbxassigned.Text
End With
End Sub

Related

Copy an entire row from a sheet to another sheet on basis of text in a cell in VBA using For loop

From Sheet1 and Sheet2, if a cell from B column has "In Progress", then I want to copy that entire row to another Sheet4.
I want to repeat it for all rows of both the sheets.
Sub Demo1()
Dim wb As Workbook
Dim ws As Worksheet, sh As Worksheet
Dim lastrow As Long
Dim w As Integer
Dim i As Integer
Set wb = Workbooks(Book1)
Set ws = Worksheets("Sheet4")
Set sh = ActiveSheet
For w = 1 To wb.Sheets.Count
For i = 1 To lastrow
If ActiveSheetCells(i, 2).Value = "In Progress" Then
wb.ws.Cells(1, 1).Insert
Else
If Cells(i, 2).Value = "" And i < 50 Then
ActiveCell.Offset(1, 0).Select
End If
Cells(i, 2).Value = "" And i > 49
Next i
Next w
End Sub
Error Message
Sheet 1
Sheet 2
Sheet 3
Quick review on your code, based on my comments to the post (untested):
Sub Demo1()
Dim wb As Workbook: Set wb = Workbooks("Book1")
Dim destinationSheet As Worksheet: Set destinationSheet = wb.Worksheets("Sheet4")
Dim sourceSheet As Worksheet: Set sourceSheet = ActiveSheet
With sourceSheet
Dim lastRowSource As Long: lastRowSource = .Cells(.Rows.Count, 1).End(xlUp).Row
Dim w As Long, i As Long
For w = 1 To wb.Sheets.Count
For i = 1 To lastRowSource
If .Cells(i, 2).Value = "In Progress" Then
destinationSheet.Cells(1, 1).Insert
Else
If .Cells(i, 2).Value = "" And i < 50 Then
'Why are you Selecting and what are you doing with it?
.Cells(i,X).Offset(1, 0).Select 'Change from "activeCell" to an actual cell reference as you don't change the activecell when looping...
End If
Cells(i, 2).Value = "" And i > 49 'Is this supposed to be another If statement?
End If 'Added
Next i
Next w
End With
Don't use Integer, use Long; the prior gets converted within VBA so you can save the processing with using the latter.
Use descriptive variable names so you're not lost in 10 months re-looking at your code, or having someone else look at your code. For the most part, people should be able to understand what's happening without the use of excessive comments.
Do your best to not have a wall of variables. If you can dimension a variable just as it's being used, you're pairing things together and might catch that x as long when you're using it as a string a lot faster.
You have a .Select and nothing happens with that. Additionally, included as a comment, using ActiveCell is probably not what you want... use a direct cell reference. Note that when you loop, VBA will change its references, however it does not physically change its activecell.
You have what appears to be another If statement which does not include any If / Then for the i > 49 bit.
The culprit of your error is the lack of End If, which is now placed with the comment Added.

Macro to copies value of a cell to another sheet but retain destination Format

I have a Sheet named "Daily Data" and One Sheet named "JPY Dly". I created a button and wrote a Macro to import data from another file and place into cells A1:D1 in "Daily Data".
I then need to Copy and Paste those VALUES into the next available cells in specific columns of Sheet "JPY Dly".
I used Offset in the Paste portion of the code but when the Paste occurs, the data does not keep the destination cells formatting. All I want is the VALUES of the cells in "Daily Data" to be copied over and for them to assume the pre-determined formatting of cells in "JPY Dly".
Here is the code that I am using.
Sub Import_DailyData()
Workbooks.Open "C:\Users\dbrown1\Downloads\exchange.csv"
'Opens the dowloaded file from the web
Workbooks("exchange.csv").Worksheets("exchange").Range("A8:AN9").Copy _
Workbooks("FOREX TEST.xlsm").Worksheets("Daily Data").Range("A1")
'Copies the daily data into FOREX Workbook
Workbooks("exchange.csv").Close SaveChanges:=False
'Closes the downloaded sheet without saving
Kill ("C:\Users\dbrown1\Downloads\exchange.csv")
'Insert the "Write to sheets" portion of the Sub in here
Worksheets("Daily Data").Range("A2").Copy Sheets("JPY Dly").Range("C2000").End(xlUp).Offset(1, 0)
Worksheets("Daily Data").Range("F2").Copy Sheets("JPY Dly").Range("E2000").End(xlUp).Offset(1, 0)
Worksheets("Daily Data").Range("G2").Copy Sheets("JPY Dly").Range("F2000").End(xlUp).Offset(1, 0)
Worksheets("Daily Data").Range("E2").Copy Sheets("JPY Dly").Range("G2000").End(xlUp).Offset(1, 0)
'Below this you will see the ClearContents portion of the code
Worksheets("Daily Data").Range("A1:AN2").ClearContents
End Sub
Can you please tell me how to paste the Values only from "Daily Data" and them assume the formatting of the cells in "JPY Dly"?
UPDATE
Here is updated code recommended by chrisnielsen and the screenshot from the downloaded "exchange"file.
Sub Import_DailyData()
Dim wbCSV As Workbook
Dim wsCSV As Worksheet
Dim wsDestination As Worksheet
Dim DestRow As Long
Set wbCSV = Workbooks.Open("C:\Users\dbrown1\Downloads\exchange.csv")
Set wsCSV = wbCSV.Worksheets("exchange")
'Opens the dowloaded file from the web
Set wsDestination = ThisWorkbook.Worksheets("JPY Dly")
'Copies the daily data into FOREX Workbook
'Closes the downloaded sheet without saving
'Insert the "Write to sheets" portion of the Sub in here
With wsDestination
DestRow = .Cells(.Rows.Count, 3).End(xlUp) + 1
' Copy data
.Cells(DestRow, 3).Value = wsCSV.Cells(2, 1).Value
.Cells(DestRow, 5).Value = wsCSV.Cells(2, 3).Value
.Cells(DestRow, 6).Value = wsCSV.Cells(2, 4).Value
.Cells(DestRow, 7).Value = wsCSV.Cells(2, 2).Value
End With
'Below this you will see the ClearContents portion of the code
'Worksheets("Daily Data").Range("A1:AN2").ClearContents
Workbooks("exchange.csv").Close SaveChanges:=False
'Kill ("C:\Users\dbrown1\Downloads\exchange.csv")
End Sub
While Copy/Paste Values will work, it's cleaner to use the values properties of the source and destination cells. This will retain destination cell formats.
Also, there are a number of other opertunities for improvement
Use Workbook and Workssheet references
No need for the intermediate Daily Data Sheet.
No need to repeat the .End(xlUp) bits
No need for the ( ) on the Kill line (in fact this has side effects that, while not a problem here, will eventually bite you)
Sub Import_DailyData()
Dim wbCSV As Workbook
Dim wsCSV As Worksheet
Dim wsDestination As Worksheet
Dim DestRow As Long
'Open the dowloaded file from the web, and get references
Set wbCSV = Workbooks.Open("C:\Users\dbrown1\Downloads\exchange.csv")
Set wsCSV = wbCSV.Worksheets("exchange")
' Reference the destination
Set wsDestination = ThisWorkbook.Worksheets("JPY Dly") ' Assuming FOREX TEST.xlsm contains this code
' If FOREX TEST.xlsm does not contains this code, use this instead of the previous line
'Set wsDestination = Application.Workbooks("FOREX TEST.xlsm").Worksheets("JPY Dly")
' get destination row
With wsDestination
DestRow = .Cells(.Rows.Count, 3).End(xlUp).Row + 1
' Copy data
.Cells(DestRow, 3).Value = wsCSV.Cells(2, 1).Value
.Cells(DestRow, 5).Value = wsCSV.Cells(2, 6).Value
.Cells(DestRow, 6).Value = wsCSV.Cells(2, 7).Value
.Cells(DestRow, 7).Value = wsCSV.Cells(2, 5).Value
End With
'Close and delete the downloaded workbook without saving
wbCSV.Close SaveChanges:=False
Kill "C:\Users\dbrown1\Downloads\exchange.csv"
End Sub
Building on ACCitonMan's comment to use paste special. The following code takes the text from cell A1 and pastes it into cell A2 while keeping whatever formatting is in cell A2.
Sub pasteSpec()
Dim ws As Excel.Worksheet
Dim cRng As Excel.Range
Dim pRng As Excel.Range
Set ws = ThisWorkbook.Worksheets(1)
Set cRng = ws.Range("A1")
Set pRng = ws.Range("A2")
cRng.Copy
pRng.PasteSpecial Paste:=xlPasteValuesAndNumberFormats
Application.CutCopyMode = False 'stops marching ants when using .copy
End Sub
Additional paste types can be found in the documentation here.

VBA for loop only iterating once

I'm having trouble with this VBA - my for loop only iterates once, and when it increments it says that the method "Cells" in object "Worksheet" failed. It worked the first iteration though... I think my StatusUpdate function is breaking it, but when I comment it out, it fails anyway. Does anything stand out in the main sub to anyone? Happy to post more code if needed.
Sub CreateSlides()
Dim XLapp As New Excel.Workbook
Dim WS As New Excel.Worksheet
Set XLapp = Excel.Workbooks.Open("J:\OPERATIONS\CAPITAL PROJECTS\Clara\test.xlsx")
Set WS = XLapp.Sheets(1)
XLapp.Activate
WS.Select
Dim CD As Integer
CD = 0
Dim cell As Range
Dim i As Integer
Dim LastRow As Integer
LastRow = WS.Cells(WS.Rows.Count, 1).End(xlUp).Row
'Delete old slides
If ActivePresentation.Slides.Count > 1 Then
Call DeleteSlides
End If
'Loop through each used row in Column A
For i = 2 To LastRow
CD = WS.Cells(i, 35).Value
ActivePresentation.Slides(1).Copy
ActivePresentation.Slides.Paste (ActivePresentation.Slides.Count + 1)
ActivePresentation.Slides(ActivePresentation.Slides.Count).Shapes("project").TextFrame.TextRange = WS.Cells(i, 7).Value
ActivePresentation.Slides(ActivePresentation.Slides.Count).Shapes("park location").TextFrame.TextRange = WS.Cells(i, 9).Value
ActivePresentation.Slides(ActivePresentation.Slides.Count).Shapes("cb").TextFrame.TextRange = Right(WS.Cells(i, 36).Text, 2)
ActivePresentation.Slides(ActivePresentation.Slides.Count).Shapes("cm").TextFrame.TextRange = (CouncilMember(CD))
ActivePresentation.Slides(ActivePresentation.Slides.Count).Shapes("scope").TextFrame.TextRange = WS.Cells(i, 8).Value
ActivePresentation.Slides(ActivePresentation.Slides.Count).Shapes("funding").TextFrame.TextRange = FundingEst(i)
ActivePresentation.Slides(ActivePresentation.Slides.Count).Shapes("status").TextFrame.TextRange = StatusUpdate(i)
Next
End Sub
you a re not running through column a but to the 35th column in the sheet. change
CD = WS.Cells(i, 35).Value
to
CD = WS.Cells(i, 1).Value
Also, if whatever is in those cells is not an integer, but text or something else, you will get an error?

I cant able to pull the information from the main source

I created a userform that will autofill in all the information using the ID# but I cant pull the source from the specific folder, workbook and range.
Here is my code:
Private Sub TextBox4_Change()
Dim rSource As Range
If Not r Is Nothing Then
'// Get value in cell r.row, column 2 into textbox2
TextBox2.Text = Sheet1.Cells(r.Row, 4).Value
ComboBox3.Value = Sheet1.Cells(r.Row, 6).Value
ComboBox4.Value = Sheet1.Cells(r.Row, 8).Value
ComboBox5.Value = Sheet1.Cells(r.Row, 9).Value
End If
End sub
Thank you!
See my answer in the code below (explanation inside the code as comments):
Option Explicit
Private Sub TextBox4_Change()
Dim wb As Workbook
Dim rSource As Range
' === first set the Workbook object ===
' if the workbook (Excel file) is already open >> use the line below
Set wb = Workbooks("Request ID.xlsm")
' if its close, then use the alternative line below
Set wb = Workbooks.Open("\\Path\")
' now use the Find function
Set rSource = wb.Worksheets("Sheet1").Range("A:A").Find(What:=TextBox4.Text, LookAt:=xlWhole, MatchCase:=False)
If Not rSource Is Nothing Then '<-- you need to use the same Range variable you used for the Find
'// Get value in cell r.row, column 2 into textbox2
TextBox2.Text = Sheet1.Cells(rSource.Row, 4).Value
ComboBox3.Value = Sheet1.Cells(rSource.Row, 6).Value
ComboBox4.Value = Sheet1.Cells(rSource.Row, 8).Value
ComboBox5.Value = Sheet1.Cells(rSource.Row, 9).Value
End If
End Sub

Macro runs but no data is pasted

First off, I am extremely new to excel vba. I have some code that works well in one workbook but doesn't work in the workbook I need it in. When using F8, it skips over the portion of the code beginning with If Cells(i, 4) = customername Then through End If.
I have searched for several days trying to find an answer online. When I run the macro, the screen flashes but the data disappears. Here is the code I am trying to use, any help will be greatly appreciated.
Sub CustomerReport()
Dim datasheet As Worksheet
Dim reportsheet As Worksheet
Dim customername As String
Dim finalrow As Integer
Dim i As Integer
Set datasheet = Sheet3
Set reportsheet = Sheet8
customername = reportsheet.Range("D6").Value
reportsheet.Range("C8:M500").ClearContents
datasheet.Select
finalrow = Cells(Rows.Count, 1).End(xlUp).Row
For i = 8 To finalrow
If Cells(i, 4) = customername Then
Range(Cells(i, 3), Cells(i, 13)).Copy
reportsheet.Select
Range("C200").End(xlUp).Offset(1, 0).PasteSpecial xlPasteFormulasAndNumberFormats
datasheet.Select
End If
Next i
reportsheet.Select
Range("D6").Select
End Sub

Resources