I am trying to generate multiple Excel file from a list in excel. Below are the code i tried but got runtime error 70.
The excel i use are (which can be download here: https://drive.google.com/folderview?id=0B7u1K6cUEOzeWURZWWd3NjQ4R0k&usp=sharing)
1) BasicInvoice.xlsx
2) 2011.xlsx
Private Sub CommandButton1_Click()
Dim Name As String
Dim invoicenumber As Long
Dim r As Long
Dim path As String
Dim myfilename As String
lastrow = Sheets("1").Range("A" & Rows.Count).End(xlUp).Row
r = 2
For r = 2 To lastrow
Date = Sheets("1").Cells(r, 1).Value
invoicenumber = Sheets("1").Cells(r, 2).Value
Name = Sheets("1").Cells(r, 3).Value
Description = Sheets("1").Cells(r, 4).Value
Amount = Sheets("1").Cells(r, 5).Value
Workbooks.Open ("BasicInvoice.xlsx")
ActiveWorkbook.Sheets("BasicInvoice").Activate
ActiveWorkbook.Sheets("BasicInvoice").Range("E9").Value = Date
ActiveWorkbook.Sheets("BasicInvoice").Range("E10").Value = invoicenumber
ActiveWorkbook.Sheets("BasicInvoice").Range("B9").Value = Name
ActiveWorkbook.Sheets("BasicInvoice").Range("B16").Value = Description
ActiveWorkbook.Sheets("BasicInvoice").Range("E16").Value = Amount
path = "C:\invoices\"
ActiveWorkbook.SaveCopyAs Filename:=path & invoicenumber & ".xlsx"
myfilename = ActiveWorkbook.FullName
Application.DisplayAlerts = True
ActiveWorkbook.PrintOut copies:=1
ActiveWorkbook.Close SaveChanges:=False
nextrow:
Next r
End Sub
RunTime Error 70 indicates that you're unable to write to something write protected. What line are you getting the error on?
Check to make sure that C:/Invoices folder actually exists on your hard drive.
Below is a tidy up of your code while I'm here.
Private Sub CommandButton1_Click()
Dim wbInv As Workbook, wsInv As Worksheet
Dim wbSrc As Workbook, wsSrc As Worksheet
Dim lastrow As Long, r As Long
Dim path As String
Set wbSrc = ThisWorkbook
Set wsSrc = wbSrc.Sheets("1")
Set wbInv = Workbooks.Open("BasicInvoice.xlsx")
Set wsInv = wbInv.Sheets("BasicInvoice")
path = "C:\invoices\"
lastrow = wsSrc.Range("A" & Rows.Count).End(xlUp).Row
Application.ScreenUpdating = False
For r = 2 To lastrow
With wsInv
.Range("E9").Value = wsSrc.Cells(r, 1).Value
.Range("E10").Value = wsSrc.Cells(r, 2).Value
.Range("B9").Value = wsSrc.Cells(r, 3).Value
.Range("B16").Value = wsSrc.Cells(r, 4).Value
.Range("E16").Value = wsSrc.Cells(r, 6).Value
End With
With wbInv
.SaveCopyAs Filename:=path & wsInv.Range("E10").Value & ".xlsx"
.PrintOut copies:=1
End With
Next r
wbInv.Close SaveChanges = False
Application.ScreenUpdating = True
End Sub
Related
Been trying to figure out how to copy a cell from worksheet A and paste it down a column in Worksheet B until it matches the same amount of rows as an adjacent column. Take the following screenshot for example. How would I properly accomplish this in VBA? Been trying to figure this out for a while now. All I've been able to do is copy the cell and paste it adjacent to the last cell in the adjacent column instead of down the entire column. The worksheet I'm copying data from is pictured below.
Copy From SpreadSheet down below
Paste to SpreadSheet down below
Current Code
Sub pullSecEquipment()
Dim path As String
Dim ThisWB As String
Dim wbDest As Workbook
Dim shtDest As Worksheet
Dim shtPull As Worksheet
Dim Filename As String
Dim Wkb As Workbook
Dim CopyRng As Range, DestRng As Range
Dim lRow As Integer
Dim destLRow As Integer
Dim Lastrow As Long
Dim FirstRow As Long
Dim UpdateDate As String
ThisWB = ActiveWorkbook.Name
Dim selectedFolder
With Application.FileDialog(msoFileDialogFolderPicker)
.Show
selectedFolder = .SelectedItems(1) & "\"
End With
path = selectedFolder
Application.EnableEvents = False
Application.ScreenUpdating = False
Set shtDest = Workbooks("GPnewchapterTEST2.xlsm").Worksheets("START")
'clear content of destination table
shtDest.Rows("8:" & Rows.Count).ClearContents
Filename = Dir(path & "\*.xls*", vbNormal)
If Len(Filename) = 0 Then Exit Sub
Do Until Filename = vbNullString
Set Wkb = Workbooks.Open(Filename:=path & "\" & Filename)
'MsgBox Filename
'''''
'SEC
'''''
If InStr(Filename, "Equipment") <> 0 Then
Dim range1 As Range
Set range1 = Range("E:K")
'For Each Wkb In Application.Workbooks
'For Each shtDest In Wkb.Worksheets
'Set shtPull = Wkb.Sheets(1)
'If shtPull.Name Like "*-*" Then
'last row
destLRow = Wkb.Sheets(1).Cells.Find(what:="*", SearchOrder:=xlRows, SearchDirection:=xlPrevious, LookIn:=xlValues).Row
'1st row
lRow = Wkb.Sheets(1).Cells.Find(what:="EQUIPMENT DESCRIPTION", SearchOrder:=xlRows, SearchDirection:=xlPrevious, LookIn:=xlValues).Row + 1
'STHours
Dim i As Integer
For i = lRow To destLRow
Set CopyRng = Wkb.Sheets(1).Range(Cells(i, 5).Address, Cells(i, 11).Address)
Set DestRng = shtDest.Range("O" & shtDest.Cells(Rows.Count, "O").End(xlUp).Row + 1)
CopyRng.Copy
DestRng.PasteSpecial Transpose:=True
Application.CutCopyMode = False 'Clear Clipboard
Set CopyRng = Wkb.Sheets(1).Range(Cells(i, 1).Address, Cells(i, 1).Address)
Set DestRng = shtDest.Range("C" & shtDest.Cells(Rows.Count, "O").End(xlDown).Row)
CopyRng.Copy
DestRng.PasteSpecial Transpose:=True
Application.CutCopyMode = False 'Clear Clipboard
Set CopyRng = Wkb.Sheets(1).Range(Cells(i, 3).Address, Cells(i, 3).Address)
Set DestRng = shtDest.Range("S" & shtDest.Cells(Rows.Count, "O").End(xlUp).Row)
CopyRng.Copy
DestRng.PasteSpecial Transpose:=True
Application.CutCopyMode = False 'Clear Clipboard
i = i + 2
Next i
'Dim cell As Integer
'Dim empname As String
'destLRow = 8 '' find out how to find first available row
'For cell = 2 To lRow
'empname = Wkb.Sheets(1).Cells(cell, 3).Value & " " & Wkb.Sheets(1).Cells(cell, 4).Value
' shtDest.Cells(8, 5).Value = empname
'shtDest.Cells(8, 1).Value = "Service Electric"
'Next cell
' Wkb.Close Save = False
End If
'End If
Filename = Dir()
Loop
MsgBox "Done!"
End Sub
if you want to do in VBA and want to copy one value in "ALL" column
Cells(1,1).Copy Columns(1)
I am trying to run some VBA code to generate an automated invoice, but I am receiving the following error:
Error 9 subscript out of range
for this code.
lastrow = Sheets(“CustomerDetails”).Range(“A” & Rows.Count).End(xlUp).Row
Any idea what could be causing this?
Private Sub CommandButton1_Click()
Dim customername As String
Dim customeraddress As String
Dim invoicenumber As Long
Dim r As Long
Dim mydate As String
Dim path As String
Dim myfilename As String
lastrow = Sheets(“CustomerDetails”).Range(“A” & Rows.Count).End(xlUp).Row
r = 2
For r = 2 To lastrow
If Cells(r, 17).Value = “done” Then GoTo nextrow
customername = Sheets(“CustomerDetails”).Cells(r, 1).Value
customeraddress = Sheets(“CustomerDetails”).Cells(r, 2).Value
invoicenumber = Sheets(“CustomerDetails”).Cells(r, 6).Value
quantity = Sheets(“CustomerDetails”).Cells(r, 18).Value
Description = Sheets(“CustomerDetails”).Cells(r, 19).Value
UnitPrice = Sheets(“CustomerDetails”).Cells(r, 20).Value
SalesTaxRate = Sheets(“CustomerDetails”).Cells(r, 16).Value
Cells(r, 17).Value = “done”
Application.DisplayAlerts = False
Workbooks.Open (“C \ invoices \ BasicInvoice.xlsx”)
ActiveWorkbook.Sheets(“BasicInvoice”).Activate
ActiveWorkbook.Sheets(“BasicInvoice”).Range(“I8”).Value = invoicenumber
ActiveWorkbook.Sheets(“BasicInvoice”).Range(“C8”).Value = customername
ActiveWorkbook.Sheets(“BasicInvoice”).Range(“C9”).Value = customeraddress
ActiveWorkbook.Sheets(“BasicInvoice”).Range(“B21”).Value = quantity
ActiveWorkbook.Sheets(“BasicInvoice”).Range(“C21”).Value = Description
ActiveWorkbook.Sheets(“BasicInvoice”).Range(“H21”).Value = UnitPrice
ActiveWorkbook.Sheets(“BasicInvoice”).Range(“D18”).Value = SalesTaxRate
path = “C \ invoices \ ”
mydate = Date
mydate = Format(mydate, “mm_dd_yyyy”)
ActiveWorkbook.SaveAs Filename:=path & invoicenumber & “ - ” & customername
& “ - ” & mydate & “.xlsx”
myfilename = ActiveWorkbook.FullName
SetAttr myfilename, vbReadOnly
Application.DisplayAlerts = True
'ActiveWorkbook.PrintOut copies:=1
ActiveWorkbook.Close SaveChanges:=False
nextrow:
Next r
End Sub
This is the function I have saved in my personal macro workbook:
Function LastRow(ByVal ws As Worksheet, Optional ByVal col As Variant = 1) As Long
With ws
LastRow = .Cells(.Rows.Count, col).End(xlUp).Row
End With
End Function
It is something that I use daily which is why it's there, and you might want to do the same if it's causing you problems
so get rid of that line completely, copy the above code to your module, then whatever you were using lastrow for, update it to include the worksheet.
You would call this function like this (assuming that you don't have a declaration for your workbook):
... = LastRow(Worksheets("CustomerDetails"))
Edit: I had to completely rewrite your code, so please make sure everything works
Code:
Option Explicit
Function LastRow(ByVal ws As Worksheet, Optional ByVal col As Variant = 1) As Long
With ws
LastRow = .Cells(.Rows.Count, col).End(xlUp).Row
End With
End Function
Private Sub CommandButton1_Click()
Const path$ = "C:\invoices\"
Dim customername As String, customeraddress As String, invoicenumber As Long
Dim r As Long, mydate As String, myfilename As String, wbInv As Workbook
Dim quantity, Description, UnitPrice, SalesTaxRate
Dim tempWB As Workbook
Dim wsCD As Worksheet
Set wsCD = ThisWorkbook.Worksheets("CustomerDetails")
For r = 2 To LastRow(wsCD)
If Not Cells(r, 17).Value = "done" Then
With wsCD
customername = .Cells(r, 1).Value
customeraddress = .Cells(r, 2).Value
invoicenumber = .Cells(r, 6).Value
quantity = .Cells(r, 18).Value
Description = .Cells(r, 19).Value
UnitPrice = .Cells(r, 20).Value
SalesTaxRate = .Cells(r, 16).Value
.Cells(r, 17).Value = "done"
End With
Application.DisplayAlerts = False
Set wbInv = Workbooks.Open("C:\invoices\BasicInvoice.xlsx")
With wbInv.Worksheets("BasicInvoice")
.Range("I8").Value = invoicenumber
.Range("C8").Value = customername
.Range("C9").Value = customeraddress
.Range("B21").Value = quantity
.Range("C21").Value = Description
.Range("H21").Value = UnitPrice
.Range("D18").Value = SalesTaxRate
End With
mydate = Format(Date, "mm_dd_yyyy")
wbInv.SaveAs Filename:=path & invoicenumber & " - " & customername & _
" - " & mydate & ".xlsx"
myfilename = ActiveWorkbook.FullName
SetAttr myfilename, vbReadOnly
Application.DisplayAlerts = True
'ActiveWorkbook.PrintOut copies:=1
wbInv.Close SaveChanges:=False
Set wbInv = Nothing
Set tempWB = Nothing
End If
Next r
End Sub
I'm working on a VBA code that creates multiple sheets from a source (Sheets). I'm trying to save them separately in a CSV format to use them for batch input. However, the requirement is that the saved worksheets must stay in "a column separation format" while in a CSV file.
Here is where I'm at:
For i = 0 To nb
If Sheets("PjtDef").Range("A2").Offset(k + i, 0).Value <> "" Then
Sheets("PjtDef").Range("A2").Offset(k + i, 0).Select
Sheets("PjtDef").Range("A1", ActiveCell).EntireRow.Copy
Sheets.Add
ActiveSheet.Name = h
ActiveSheet.Paste
Worksheets("PjtDef").Activate
Sheets("PjtDef").Range("A2").Offset(k + i, 0).Select
Range("A2", ActiveCell).EntireRow.Delete Shift:=xlUp
h = h + 1
Else: i = nb
End If
Next i
Dim xWs As Worksheet
Dim xcsvFile As String
For Each Scut In Application.ActiveWorkbook.Worksheets
Scut.Copy
Name = CurDir & "\" & Scut.Name & ".csv"
Application.ActiveWorkbook.SaveAs Filename:=Name, _
FileFormat:=xlCSV, CreateBackup:=False
Application.ActiveWorkbook.Saved = True
Application.ActiveWorkbook.Close
Next
Application.ScreenUpdating = True
End Sub
I have next code working:
Sub ExportFile()
Const myDelim As String = "|"
Dim Sheet As Object
Set Sheet = Worksheets
For p = 1 To 2 'you could use sheet.count
Sheet(p).Activate
Dim ws As Worksheet
Set ws = ActiveSheet
Dim r As Long, c As Long, i As Long, j As Long
r = ws.Cells.Find(What:="*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
c = ws.Cells.Find(What:="*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
Dim myPath As String
myPath = ThisWorkbook.Path & "\"
Dim myFile As String
filename = ws.name
myFile = myPath & filename & ".extention"
Dim obj As Object
Set obj = CreateObject("ADODB.Stream")
obj.Type = 2
obj.Charset = "ASCII"
obj.Open
Dim v() As Variant
ReDim v(1 To c)
For i = 3 To r - 1
For j = 1 To c
v(j) = ws.Cells(i, j).Text
Next
obj.WriteText Join(v, myDelim), 1
Next
obj.SaveToFile myFile, 2
End Sub
This writes all sheet to a file separating cells in rows by "|"
I have written/hashed together a programme for copying in a row of data for when the row meets a certain criteria (column A = "1") for all workbooks sitting in a test folder on my desktop; the programme worked initially but now pulls up an error here:
ws.Range(ws.Cells(r, 1), Cells(r, 20)).Copy Destination:=ThisWorkbook.Sheets("SummaryAccrual").Range("A" & lr2 + 1)
Once this is sorted, I'm also concerned that this method of copying and pasting will paste formulas and not values, is there an easy way to paste values?
Thanks for all your help, I super appreciate it!
My Code
Option Explicit
Sub AccrualCombiner()
Dim Path As String
Dim FileName As String
Dim Wkb As Workbook
Dim cWkb As Workbook
Dim ws As Worksheet
Dim answer As Integer
Dim lr As Long, lr2 As Long, r As Long
Dim rc As Object
Application.EnableEvents = False
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.AskToUpdateLinks = False
answer = MsgBox("Would you like to combine Accruals for current period?", vbYesNo + vbQuestion, "Confirmation")
If answer = vbYes Then
Set cWkb = Application.ActiveWorkbook
lr2 = ThisWorkbook.Sheets("SummaryAccrual").Cells(Rows.Count, "A").End(xlUp).Row
Path = "C:\Users\alexander.neale\Desktop\Test"
FileName = Dir(Path & "\*.xls", vbNormal)
Do Until FileName = ""
Set Wkb = Workbooks.Open(FileName:=Path & "\" & FileName)
For Each ws In Wkb.Worksheets
For r = 14 To 60 Step 1
If ws.Range("A" & r).Value = "1" Then
ws.Range(ws.Cells(r, 1), Cells(r, 20)).Copy Destination:=ThisWorkbook.Sheets("SummaryAccrual").Range("A" & lr2 + 1)
lr2 = ThisWorkbook.Sheets("SummaryAccrual").Cells(Rows.Count, "A").End(xlUp).Row
End If
Next r
Next ws
Wkb.Close False
FileName = Dir()
Loop
Application.EnableEvents = True
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.AskToUpdateLinks = True
End If
End Sub
since you're interested in pasting values only, this should be faster:
Option Explicit
Sub AccrualCombiner()
Dim Path As String
Dim FileName As String
Dim Wkb As Workbook
Dim ws As Worksheet
Dim answer As Integer
Dim r As Long
answer = MsgBox("Would you like to combine Accruals for current period?", vbYesNo + vbQuestion, "Confirmation")
If answer = vbYes Then
Application.EnableEvents = False
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Application.AskToUpdateLinks = False
Path = "C:\Users\alexander.neale\Desktop\Test"
With ThisWorkbook.Worksheets("SummaryAccrual")
FileName = Dir(Path & "\*.xls", vbNormal)
Do Until FileName = ""
Set Wkb = Workbooks.Open(FileName:=Path & "\" & FileName)
For Each ws In Wkb.Worksheets
If WorksheetFunction.CountIf(ws.Range(ws.Cells(14, 1), ws.Cells(60, 1)), "1") > 0 Then
For r = 14 To 60 Step 1
If ws.Range("A" & r).Value = "1" Then
.Cells(.Rows.COUNT, "A").End(xlUp).Offset(1).Resize(, 20).Value = ws.Range(ws.Cells(r, 1), ws.Cells(r, 20)).Value
End If
Next r
End If
Next ws
Wkb.Close False
FileName = Dir()
Loop
End With
Application.EnableEvents = True
Application.ScreenUpdating = True
Application.DisplayAlerts = True
Application.AskToUpdateLinks = True
End If
End Sub
Here's your problem:
ws.Range(ws.Cells(r, 1), Cells(r, 20)).Copy
the second Cells has no sheet specified so it will assume you mean the active sheet. If the active sheet is not ws then it will fail because a range can't span multiple sheets. Hence use
ws.Range(ws.Cells(r, 1), ws.Cells(r, 20)).Copy
or
With ws
.Range(.Cells(r, 1), .Cells(r, 20)).Copy ....
End With
edit: to paste only values, either just set the .Value property of the range, like user3598756 suggested:
ThisWorkbook.Sheets("SummaryAccrual").Range("A" & lr2 + 1).Resize(1, 20).Value = ws.Range(ws.Cells(r, 1), ws.Cells(r, 20)).Value
or use PasteSpecial with the xlPasteValues option:
ws.Range(ws.Cells(r, 1), ws.Cells(r, 20)).Copy
ThisWorkbook.Worksheets("SummaryAccrual").Range("A" & lr2 + 1).PasteSpecial xlPasteValues
the first option usually is much faster.
I am new to VBA and If anyone can help, I'd greatly appreciate it. I just need help in simple VBA loop in following code.
I am trying to loop through excel files in a folder and copy specific data from source Worksheet in all files to a new workbook (sheet 2). I have a code which does 70% of the job but I am having difficulty in picking some data and copying it in specific format.
Option Explicit
Const FOLDER_PATH = "C:\Temp\" 'REMEMBER END BACKSLASH
Sub ImportWorksheets()
'=============================================
'Process all Excel files in specified folder
'=============================================
Dim sFile As String 'file to process
Dim wsTarget As Worksheet
Dim wbSource As Workbook
Dim wsSource As Worksheet
Dim rowTarget As Long 'output row
Dim FirstRow As Long, LastRow As Long
FirstRow = 1
LastRow = 5
Dim RowRange As Range
rowTarget = 2
'check the folder exists
If Not FileFolderExists(FOLDER_PATH) Then
MsgBox "Specified folder does not exist, exiting!"
Exit Sub
End If
'reset application settings in event of error
On Error Goto errHandler
Application.ScreenUpdating = False
'set up the target worksheet
Set wsTarget = Sheets("Sheet2")
'loop through the Excel files in the folder
sFile = Dir(FOLDER_PATH & "*.xls*")
Do Until sFile = ""
'open the source file and set the source worksheet - ASSUMED WORKSHEET(1)
Set wbSource = Workbooks.Open(FOLDER_PATH & sFile)
Set wsSource = Sheets("DispForm") 'EDIT IF NECESSARY
'import the data
With wsTarget
For Each rw In RowRange
If wsSource.Cells(rw.Row, 1) & wsSource.Cells(rw.Row + 1, 1) = "" Then
Exit For
End If
.Range("A" & rowTarget).Value = wsSource.Range("B1").Value
.Range("B" & rowTarget).Value = wsSource.Cells(rw.Row, 2)
.Range("C" & rowTarget).Value = wsSource.Cells(rw.Row, 4)
.Range("D" & rowTarget).Value = sFile
rowTarget = rowTarget + 1
Next rw
End With
'close the source workbook, increment the output row and get the next file
wbSource.Close SaveChanges:=False
rowTarget = rowTarget + 1
sFile = Dir()
Loop
errHandler:
On Error Resume Next
Application.ScreenUpdating = True
'tidy up
Set wsSource = Nothing
Set wbSource = Nothing
Set wsTarget = Nothing
End Sub
Private Function FileFolderExists(strPath As String) As Boolean
If Not Dir(strPath, vbDirectory) = vbNullString Then FileFolderExists = True
End Function
you only copy one row of data from your source file. so you need either to have a loop inside your file loop to loop all the rows, or to have a range to select all the rows.
try something like the following:
Dim FirstRow As Long, LastRow As Long
FirstRow = 9
LastRow = 100
Set rowRange = wsSource.Range("A" & FirstRow & ":A" & LastRow)
With wsTarget
For Each rw In rowRange
If wsSource.Cells(rw.Row, 2) = "" Then
Exit For
End If
.Range("A" & rowTarget).Value = wsSource.Cells(rw.Row, 2)
.Range("B" & rowTarget).Value = wsSource.Cells(rw.Row, 3)
Next rw
End With