I am looking to copy a range of data (columns A:M) on a temporary excel worksheet, with a "tmp" prefix into a worksheet designed to crunch all of this data output into a useable report.
Currently, the user will simply manually copy the temporary output into the report making tool, then run the macro.
Is it possible to automate this data input?
Aaron, SO is used for teaching. But, since I got bored, and in case you don't re-post this here, this is an idea of how to accomplish your goal. Keep in mind that with VBA, and probably all other languages, there's 20 different ways to accomplish the same task, but what fits each users unique scenario is what SO likes to resolve. To give you a rolling start and perhaps some motivation...
Option Explicit
Sub CopyStuff()
Dim ws As Worksheet
Dim ws2 As New Worksheet
Dim rngToCopy As Range
Dim ShtName As String
'use ActiveSheet or actual name
Set ws = ActiveSheet
Set rngToCopy = ws.UsedRange.Columns("A:M")
Set ws2 = ThisWorkbook.Worksheets.Add
'gets name for sheet
ShtName = InputBox("Please enter name for Sheet.")
'more properties to fill if needed, or adjust area to copy to
'just an example here
With ws2
.Name = "tmp" & ShtName
rngToCopy.Copy .UsedRange.Columns(.UsedRange.Columns.Count + 1)
End With
'cleanup
Set ws = nothng: Set ws2 = Nothing
Set rngToCopy = Nothing: ShtName = vbNullString
End Sub
Danny,
ExcelVBADude
Related
I am trying to sum values from my original worksheet in specific cells in my newly created worksheet, which has a template to fill out.
When I used macro recorder, it references the worksheet name, which would not be useful as the worksheet name changes depending on which worksheet I am working in when I run the code.
So I tried changing the worksheet name to a variable "XCXX".
The first argument works so I thought everything was okay, however, on the second argument, it keeps trying to open a file, when it should simply go back to XCXX and pull the values.
Is it a problem with my activesheet changing?
Sub AddWorkbooks()
Dim ChangeOrder As Range
Dim XCXX As Worksheet
Dim CoForm As Worksheet
Set XCXX = ActiveSheet
Set CoForm = Worksheets("+CO Form+")
'Set wbNew = Workbooks.Add
CoForm.Copy After:=Sheets(ActiveSheet.Index)
With CoForm
Range("A6:D6").Select
ActiveCell.FormulaR1C1 = XCXX.Range("D2").Value
Range("AD81").Select
ActiveCell.FormulaR1C1 = "='XCXX'!R[-64]C[-24]+'XCXX'!R[-64]C[-23]"
End With
End Sub
This should be close:
Sub AddWorkbooks()
Dim ChangeOrder As Range
Dim XCXX As Worksheet, wb As Workbook
Dim CoForm As Worksheet, CoFormCopy As Worksheet
Set wb = ActiveWorkbook
Set XCXX = ActiveSheet
Set CoForm = wb.Worksheets("+CO Form+")
CoForm.Copy After:=XCXX
Set CoFormCopy = XCXX.Next 'the copy of "+CO Form+"
With CoFormCopy 'assuming you want to work with the copy?
.Range("A6:D6").Value = XCXX.Range("D2").Value
.Range("AD81").FormulaR1C1 = _
Replace("='<nm>'!R[-64]C[-24]+'<nm>'!R[-64]C[-23]", "<nm>", XCXX.Name)
End With
End Sub
Note when using With you need to use a period to link (eg) Range() with the object used in the With statement, otherwise it defaults to the active sheet.
Also generally there's no need to select a range to do something with it.
I am struggling with proper syntax for setting variables as ranges...
Specifically, I'm testing a function I want to use in an app that creates new profiles and store the data, I will store that data on a hidden sheet, so they can be recalled at run time.
I'm currently construction a userform in order to create a new profile, the profile data needs to be stored to the first free column on the hidden sheet.
(where I will have to create a dynamic namedRange, so that i can use that range to save the associated data, and update the listbox in the userform)
Right now, I'm stumped by this:
Sub TestFindLastFunctions()
Dim wb As Workbook
Set wb = ThisWorkbook
'wb.activate 'shouldn't be neccesary
Dim ws As Worksheet
Set ws = sh_02CRepStorage
'ws.activate 'shoudn't be neccesary
Dim trgtCol As Long
trgtCol = LastColInSheet(ws) + 2
Debug.Print trgtCol ' so far so good
'Cells(1, trgtCol).Select 'another debug check - only works if sheet activated
Dim trgtCell As Range
Set trgtCell = ws.Cells(1, trgtCol) '<------- problem line
Debug.Print trgtCell '<----- prints "" to the immediate window.
End Sub
The LastColInSheet function is copied form Ron de bruin's page: https://www.rondebruin.nl/win/s9/win005.htm it simply returns a column number, in this case: 4.(One problem with it is if the sheet is empty, it returns an error, wondering if this can be fixed with an if statement in the function.)
I've tried many iterations of the problem line, some work but only if the storage sheet is activated, and give an error if not activate or selected, as the sheet will be hidden, I need this to work without activating the sheet, (although I could switch off screen activation?).
But I understand that it is best practice to avoid extraneous selects and activates, how can I just point directly to what I want and save that range into a variable?
It just doesn't seem like it should be so difficult, I must be missing something obvious.
It also seems like it shouldn't need so many lines of code to do something so simple.
I tried some more iterations of the "problem line" after some more searching...
-The real problem was with the debug.print line
Sub TestFindLastFunctions()
Dim wb As Workbook
Set wb = ThisWorkbook
'wb.activate 'shouldn't be neccesary
Dim ws As Worksheet
Set ws = sh_02CRepStorage
'ws.activate 'shoudn't be neccesary
Dim trgtCol As Long
trgtCol = LastColInSheet(ws) + 2
Debug.Print trgtCol ' so far so good
'Cells(1, trgtCol).Select 'debug Only works if already on sheet
Dim trgtCell As Range
'Set trgtCell = ws.Range _
(ws.Cells(1, trgtCol), ws.Cells(1, trgtCol))
' unnecessarily complex, but correct if using .range?
'but works if insisting on range
Set trgtCell = ws.Cells(1, trgtCol) 'back to original
Debug.Print trgtCell.Address '<---problem was here?
End Sub
I am trying to copy a worksheet and rename it based on a variable and that is working. The issue is that it changes the name of the template sheet in the process of copying. Any ideas how to fix it?
Sub AddAgent()
Dim wsname As String
Dim lRow As Long
wsname = ActiveWorkbook.Sheets("Summary").Range("E5").Value
Set ws = Sheets("Agent Template")
ws.Copy After:=Sheets("Summary")
Set wsNew = Sheets(Sheets("Summary").Index + 2)
wsNew.Range("C4").Value = wsname
wsNew.Name = wsname
As I understand it, the Copy() function automatically sets the new worksheet as the ActiveSheet. So you wouldn't need to find it by index. You could simply access the properties of the ActiveSheet object:
With ThisWorkbook.Worksheets
.Item("Agent Template").Copy After:=.Item("Summary")
End With
With ThisWorkbook.ActiveSheet
.Name = ThisWorkbook.Worksheets("Summary").Range("E5").Value2
.Range("C4").Value = .Name
End With
If my understanding is correct, then I'd favour this way, as you could lose control of indexing if users start moving sheets around.
You're incrementing the Index too far
Set ws = Sheets("Agent Template")
ws.Copy After:=Sheets("Summary")
Set wsNew = Sheets(Sheets("Summary").Index + 1)
Note you can get unpredictable results if any sheets are hidden:
Copy sheet and get resulting sheet object?
I am trying to execute a macro on a workbook that is downloaded from the web daily.
It has only one worksheet that changes names accordingly with the date downloaded (say: "vendas 201709294524455").
I need to set this worksheet as a variable. How can I do that with this dynamic name change?
I tried:
Dim Sh1 As Worksheet
Dim Sh2 As Worksheet
Dim FindCell As Range
Set Sh2 = ThisWorkbook.Worksheets("book1")
Set Sh1 = Workbooks("vendas.xlsm").Worksheets("*vendas*")
LastRow = Sh2.Range("d65536").End(xlUp).Row
'...rest of the code
As it only has one worksheet just use:
Set Sh1 = Workbooks("vendas.xlsm").Worksheets(1)
The Worksheets() allows for the index or a string name. With only one sheet the index is always 1 of that one sheet. See: https://msdn.microsoft.com/en-us/vba/excel-vba/articles/worksheet-object-excel
This will set Sh1 to the first worksheet in the workbook regardless of the name.
Scott Craner's solution is perfect for you. But just for anyone in future -- this is how you would do it if you want to avoid using the worksheet index (which changes if you change the order of the worksheets). Only worth using this method if you have more than one worksheet.
Sub SetWorksheet()
Dim ws As Worksheet, targetWorksheet As Worksheet
For Each ws In ThisWorkbook.Worksheets
If ws.Name Like "*test*" Then
Set targetWorksheet = ws
Exit For
End If
Next ws
'use targetWorksheet
MsgBox targetWorksheet.Name
End Sub
If there are multiple sheets like "test" (in this example), you will get the first one.
is there a way not to select workbook back and forth and copy a block of data efficiently?
this is how I am doing it right now:
Set MyWB = ActiveWorkbook
Set DataWS = MyWB.Worksheets("Data")
Set TermDataRange = DataWS.Range("celltopaste")
Workbooks("data.csv").Activate
Range("A1").CurrentRegion.Copy 'selecting block data
MyWB.Activate
TermDataRange.Select
Selection.PasteSpecial Paste:=xlPasteValues
is there a way without selecting MyWB, then the range?
also, selection.paste feels kind of wierd, I hate copying data to clipboard.
I was hoping for something like:
Workbooks("data.csv").Activate
TermDataRange = Range("A1").CurrentRegion
Thanks for your help
Selecting the range directly is as easy as meshing your three lines together:
Set TermDataRange = ActiveWorkbook.Worksheets("Data").Range("celltopaste")
edited - my mistake - I'd skipped more steps than I thought and was actually condensing three of your lines, rather than two, into one : )
(to be honest I would never normally give a seperate name to ActiveWorkbook itself, unless I needed to refer to it as a workbook later in the code)
Avoiding Copy/Paste is pretty easy. The trick is to make sure that your source range and destination range are the same size and shape - once this is true you can simply use the code
RangeA.Value = RangeB.Value
In your case, your best bet is to measure the size of your data first. e.g.
'give range("A1").current region a name just to make it less unwieldy
CopyRange = Range("A1").CurrentRegion
Datarows = CopyRange.Rows.Count
Datacols = CopyRange.Columns.Count
'set a range of same size starting from TermDataRange to move the values to
set DestRange = Range(TermDataRange, TermDataRange(offset(Datarows -1, Datacolumns -1))
'move values directly rather than via copy-paste
DestRange.Value = CopyRange.Value
Maybe you are looking for something more "clean" like this?
Option Explicit
Sub CopyValueFromSheet()
Dim MyWB As Workbook
Dim DataWS As Worksheet
Dim TermDataRange As Range
Dim OtherWB As Workbook
' To avoid screen flashing
Application.ScreenUpdating = False
Set MyWB = ThisWorkbook
Set DataWS = MyWB.Worksheets("Sheetname")
Set TermDataRange = DataWS.Range("DestinationCell")
Set OtherWB = Workbooks.Open("C:\Users\YourUsername\Desktop\CsvFileName.csv")
' When opening a csv file there is only one worksheet with the same name as the csv file
OtherWB.Worksheets("CsvFileName").Range("SourceCell").Copy
TermDataRange.PasteSpecial Paste:=xlPasteValues
Application.ScreenUpdating = True
End Sub
Edit:
Another possible way would result in storing the value of the source cell in a VBA variable and then set it to the destination cell, but it will be pretty much the same:
Dim VarValue As String
VarValue = OtherWB.Worksheets("CsvFileName").Range("SourceCell").Value
TermDataRange.Value = VarValue
HTH ;)