Transferring Data to Excel - vba

I have the following code to transfer code to excel file:
Dim SaveAsStr As String
Dim appXL As Excel.Application
Dim wbk As Excel.Workbook
Dim wst As Excel.Worksheet
Dim cn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim rs1 As ADODB.Recordset
Dim rs2 As ADODB.Recordset
Dim LR As Long
Dim startcell As Range
DoCmd.RunMacro "Guardarmcr"
Set appXL = CreateObject("Excel.Application")
appXL.Visible = True
Set wbk = appXL.Workbooks.Add
Set wst = wbk.Worksheets(1)
Set startcell = Range("D16")
Set cn = CurrentProject.AccessConnection
Set rs = New ADODB.Recordset
Set rs1 = New ADODB.Recordset
Set rs2 = New ADODB.Recordset
With rs
Set .ActiveConnection = cn
.Source = "SELECT * FROM ExcelTitulotbl"
.Open
End With
With rs1
Set .ActiveConnection = cn
.Source = "SELECT * FROM Excelotptbl"
.Open
End With
With rs2
Set .ActiveConnection = cn
.Source = "SELECT * FROM ExcelEDTUDCtbl"
.Open
End With
With wst
'.QueryTables.Add Connection:=rs, Destination:=.Range("A1")
'.QueryTables(1).Refresh
.QueryTables.Add Connection:=rs1, Destination:=.Range("d16")
.QueryTables(1).Refresh
.Range("A16").EntireRow.Delete
.Range("e2").Font.Bold = True
.Range("e2").Font.Name = "Calibri"
.Range("e2").Font.Size = 14
.Range("e2") = "VALORACION"
.Range("D5") = "Descripción"
.Range("j5") = "Profesional Colaborador"
.Range("j6") = "Profesional Chilectra"
.Range("e5") = rs("proyectoMain")
.Range("k5") = rs("Empleado")
.Range("k6") = rs("chilectramain")
.Range("B15") = "Recargo"
.Range("D15") = "Número"
.Range("E15") = "Apdto"
.Range("F14") = "Tipo"
.Range("F15") = "Ocurrencia"
.Range("g15") = "Especialidad"
.Range("h14") = "Tipo"
.Range("h15") = "Activo"
TotalE
End With
wbk.Saved = True
Set wks = Nothing
Set wbk = Nothing
Set appXL = Nothing
End Sub
Most of it works all right but if I try to run the command a Second time the worksheet opens but the vba fails showing a 1004 error. It has something to do with LR = Range("E" & Rows.Count).End(xlUp).Row. If I quit the form and enter it again it works the first time but not a second.
Will appreciate some help on this, thanks.

Looks like you are calling the TotalE sub routine, but in it you are not telling the range explicitly what workbook to use.
Activeworkbook.Range() may be better or when you add the workbook, capture the name and pass it to the sub routine.
Strange, but your only calculating the last row in column E and putting that value + 2 into column D two rows down.
All you really need is this code to replace your call to TotalE:
ActiveWorkbook.Sheets(1).Range("D" & ActiveWorkbook.Sheets(1).Range("E" & Rows.Count).End(xlUp).Row + 2) = ActiveWorkbook.Sheets(1).Range("E" & Rows.Count).End(xlUp).Row + 2
End Sub

Related

Error 3011 when doing transferspreadsheet

Running VBA through Access.
Attempting to transfer select queries from access to excel.
If I run all the code together, then I get 3011 run-time error on the 2nd DoCmd.TransferSpreadsheet.
If I comment out all the code related to PATH1, then the 2nd DoCmd.TransferSpreadhseet runs fine.
The Microsoft Access database engine could not find the object 'TabUSR1'. Make sure the object exists and that you spell its name and the path name correctly...
I have removed a good bit of code that I feel to be irrelevant to my issue. That is why there are so many variables you do not see any code for.
Dim tempR1 As String
Dim tempR2 As String
Dim tempValue1 As String
Dim tempValue2 As String
Dim tempValue3 As String
Dim tempValue4 As String
Dim tempValue5 As String
Dim dt As Date
Dim d As String
Dim row As String
Dim rngC As Range
Dim rngU As Range
Dim fpath As String
Dim strFileExists
Dim xlappC As Excel.Application
Dim xlbookC As Excel.Workbook
Dim xlsheetC As Excel.Worksheet
Dim xlappU As Excel.Application
Dim xlbookU As Excel.Workbook
Dim xlsheetU As Excel.Worksheet
fpath = "PATH1"
strFileExists = Dir(fpath)
If strFileExists <> "" Then
'set variables for Excel
Set xlappC = CreateObject("Excel.Application")
Set xlbookC = xlappC.Workbooks.Open(fpath)
Set xlsheetC = xlbookC.Worksheets("Audit Fees Remittance")
With xlappC
.Visible = False
.DisplayAlerts = False
.Workbooks.Open fpath
'Update Raw Data Cad and CSCT tab
Set xlsheetC = xlbookC.Worksheets("Raw Data CAD and CSCT")
With xlsheetC
Set rst = CurrentDb.OpenRecordset("Weekly CAN 5 Raw Data to include csct")
If rst.RecordCount > 0 Then
tempR2 = rst.RecordCount + 1
tempR2 = .Cells(.Rows.Count, "CV").End(xlUp).Offset(tempR2).Address(False, False)
tempR1 = .Cells(.Rows.Count, "A").End(xlUp).Offset(1).Address(False, False)
Set rngC = .Range(tempR1, tempR2)
rngC.Name = "TabFA8"
DoCmd.TransferSpreadsheet acExport, 10, "PATH1", True, "TabFA8"
.Rows(2).EntireRow.Delete
rst.Close
Set rst = Nothing
Else
rst.Close
Set rst = Nothing
End If
tempValue2 = "$A$2:" & tempR2
.Range(tempValue2).EntireColumn.AutoFit
tempR1 = ""
tempR2 = ""
End With
'Remit for US
fpath = "PATH2"
strFileExists = Dir(fpath)
If strFileExists <> "" Then
'set variables for Excel
Set xlappU = CreateObject("Excel.Application")
Set xlbookU = xlappU.Workbooks.Open(fpath)
Set xlsheetU = xlbookU.Worksheets("Remittance Tab")
With xlappU
.Visible = False
.DisplayAlerts = False
.Workbooks.Open fpath
'Update INTL Remittance tab
Set xlsheetU = xlbookU.Worksheets("INTL Remittance")
With xlsheetU
Set rst = CurrentDb.OpenRecordset("Weekly US 5 Remittance Tab B DHLG and Jas")
If rst.RecordCount > 0 Then
tempR2 = rst.RecordCount + 1
tempR2 = .Cells(.Rows.Count, "V").End(xlUp).Offset(tempR2).Address(False, False)
tempR1 = .Cells(.Rows.Count, "A").End(xlUp).Offset(1).Address(False, False)
If Len(tempR1) = 3 Then
row = Right(tempR1, 2)
Else
row = Right(tempR1, 3)
End If
'set range for renaming
'this will allow TransferSpreadhseet to know where to export to on the sheet
Set rngU = .Range(tempR1, tempR2)
rngU.Name = "TabUSR2"
DoCmd.TransferSpreadsheet acExport, 10, "Weekly US 5 Remittance Tab B DHLG and Jas", "PATH2", True, "TabUSR2"
'delete row with headers
.Rows(row).EntireRow.Delete
rst.Close
Set rst = Nothing
Else
rst.Close
Set rst = Nothing
End If
End With
While I cannot exactly understand or diagnose your issue, for maintenance and readability, consider separating all Excel and Access processes. Avoid walking over same opened files with both object libraries. Therefore, consider Excel's Range.CopyFromRecordset over Access's DoCmd.TransferSpreadsheet using the very recordset you create.
...
Set rst = CurrentDb.OpenRecordset("Weekly CAN 5 Raw Data to include csct")
...
Set rngC = .Range(tempR1, tempR2)
rngC.Name = "TabFA8"
rngC.CopyFromRecordset rst
rst.Close
...
Set rst = CurrentDb.OpenRecordset("Weekly US 5 Remittance Tab B DHLG and Jas")
...
Set rngU = .Range(tempR1, tempR2)
rngU.Name = "TabUSR2"
rngU.CopyFromRecordset rst
rst.Close
Parfait's suggestion of closing the workbook then doing the TransferSpreadsheet solved my issue.

I'm trying to populate my ComboBox with a query from SQL

First of all I'm new to VB so all help is very much appreciated.
I'm trying to populate a ComboBox in Excel with data from an SQL server.
The error is 'Dim cnt As ADODB.Connection' - Complie Error: User-defined type not defined
Sub Populate_ComboBox_From_SQL()
Dim cnt As ADODB.Connection
Dim rst As ADODB.Recordset
Dim stDB As String, stConn As String, stSQL As String
Dim xlCalc As XlCalculation
Dim vaData As Variant
Dim k As Long
Set cnt = New ADODB.Connection
stConn = "DSN=Backup;Trusted_Connection=Yes;APP=Microsoft Office;DATABASE=<database>"
cnt.ConnectionString = stConn
stSQL = "SELECT 'project no' FROM 'project register"
With cnt
.CursorLocation = adUseClient
.Open stConn 'Open connection.
Set rst = .Execute(stSQL)
End With
With rst
Set .ActiveConnection = Nothing 'Disconnect the recordset.
k = .Fields.Count
vaData = .GetRows
End With
cnt.Close
With TEMPLATE
With .ComboBox1
.Clear
.BoundColumn = k
.List = Application.Transpose(vaData)
.ListIndex = -1
End With
End With
Set rst = Nothing
Set cnt = Nothing
End Sub
The sheet is called TEMPLATE and the ComboBox is called ComboBox1.
I have omitted the name of the SQL server in the connection string.
Thanks in advance.

How to run access query using excel VBA?

I am fairly new to Access and I have been trying for a while to run an Access query and paste the results in Excel using VBA. I have combined some code I found and I think I almost have it but cannot figure out the last step. Here is the code:
Sub test()
Dim ws As Worksheet
Dim A As Object
Dim rs As Object
Application.DisplayAlerts = False
Set A = CreateObject("Access.Application")
Set ws = ThisWorkbook.Sheets("Sheet1")
A.Visible = True
A.OpenCurrentDatabase ("access database path")
A.DoCmd.OpenQuery ("query name")
Set rs = A.CurrentDb().QueryDefs("query name").OpenRecordset()
If Not rs.EOF Then
ws.Range("A1").CopyFromRecordset rs
End If
rs.Close
Application.DisplayAlerts = True
End Sub
I am trying to run the query and paste the results in cell A1 in sheet 1.
I get a "run time error 3219" for the line:
Set rs = A.CurrentDb().QueryDefs("query name").OpenRecordset()
Any help would be greatly appreciated.
Thanks,
G
I adapted your code to fetch data from an Access query without needing to create a full Access.Application instance. Tested and working in Excel 2010.
Const cstrPath As String = "C:\share\Access\Database2.accdb"
Const cstrQuery As String = "qryBase"
Dim dbe As Object 'DAO.DBEngine '
Dim rs As Object 'DAO.Recordset '
Dim ws As Worksheet
Application.DisplayAlerts = True 'leave alerts on during testing '
Set dbe = CreateObject("DAO.DBEngine.120")
Set rs = dbe.OpenDatabase(cstrPath).OpenRecordset(cstrQuery)
If Not rs.EOF Then
Set ws = ThisWorkbook.Sheets("Sheet1")
ws.Range("A1").CopyFromRecordset rs
End If
rs.Close
Application.DisplayAlerts = True
I would use ADODB recordset. Try the below code. Here I'm connecting to an excel workbook, but you can use the same logic for access database, you just need to change the connection string.
Private con As ADODB.Connection
Private ra As ADODB.Recordset
' SqlString = SQL Query
' Sht = Sheet Name, where the output needs to be displayed
' Rng = Range ("C5"), where the output needs to be displayed
Sub DoSql(SqlString As String, Sht As String, Rng As String, Optional IncludeHeading As Boolean = False)
Dim a As String
Dim res As Variant
Set con = New ADODB.Connection
Set ra = New ADODB.Recordset
res = ""
'a = Set the appropriate connection string for your database
'The below connection is referring to the same excel workbook which contains the macro
a = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=""" & ThisWorkbook.FullName & """;Extended Properties=""Excel 12.0 Xml;HDR=YES"";"
'MsgBox a
'MsgBox SqlString
If Not Left("" & con, 8) = "Provider" Then
con.Open a
End If
If Not ra.State = 0 Then
ra.Close
End If
ra.Open SqlString, con
If Not (ra.EOF And ra.BOF) Then
ra.MoveFirst
Sheets(Sht).Select
If IncludeHeading = True Then
For intColIndex = 0 To ra.Fields.Count - 1
Range(Rng).Offset(0, intColIndex).Value = ra.Fields(intColIndex).Name
Next
Range(Rng).Offset(1, 0).CopyFromRecordset ra
Else
Range(Rng).CopyFromRecordset ra
End If
End If
ra.Close
con.Close
End Sub

Adding borders to dynamic range SQL query using VBA

I have tried a bunch of different ideas, and I'm still stuck. I'm new to VBA, so I can't figure out how to get exactly what I need, because I don't totally understand the language.
I'm looking to add borders (both outer and inner) around each cell in the data that is returned to the query. How can I write this into the code? I'm going to attach a picture of what the user will hopefully see as well.
Here's what I have:
Sub Button1_Click()
Dim con As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim WSP1 As Worksheet
Set con = New ADODB.Connection
Set cmd = New ADODB.Command
Set rs = New ADODB.Recordset
Application.DisplayStatusBar = True
Application.StatusBar = "Contacting SQL Server..."
' Remove any values in the cells where we want to put our Stored Procedure's results.
Dim rngRange As Range
Set rngRange = Range(Cells(8, 2), Cells(Rows.Count, 1)).EntireRow
rngRange.ClearContents
' Log into our SQL Server, and run the Stored Procedure
con.Open "Provider=XXXXXXetc"
' Set up the parameter for our Stored Procedure
' (Parameter types can be adVarChar,adDate,adInteger)
cmd.Parameters.Append cmd.CreateParameter("Assembly", adVarChar, adParamInput, 10, Range("B1").Text)
Application.StatusBar = "Running stored procedure..."
cmd.CommandText = "Custom.PRO_BOM_XXXX"
Set rs = cmd.Execute(, , adCmdStoredProc)
' Copy the results to cell B7 on the first Worksheet
Set WSP1 = Worksheets(1)
WSP1.Activate
If rs.EOF = False Then WSP1.Cells(8, 2).CopyFromRecordset rs
rs.Close
Set rs = Nothing
Set cmd = Nothing
con.Close
Set con = Nothing
Application.StatusBar = "Data successfully updated."
End Sub
Current Outcome:
Expected Outcome:
You want something like:
Sub Button1_Click()
Dim con As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim WSP1 As Worksheet
Set con = New ADODB.Connection
Set cmd = New ADODB.Command
Set rs = New ADODB.Recordset
Application.DisplayStatusBar = True
Application.StatusBar = "Contacting SQL Server..."
' Remove any values in the cells where we want to put our Stored Procedure's results.
Dim rngRange As Range
Set rngRange = Range(Cells(8, 2), Cells(Rows.Count, 1)).EntireRow
rngRange.ClearContents
' Log into our SQL Server, and run the Stored Procedure
con.Open "Provider=XXXXXXetc"
' Set up the parameter for our Stored Procedure
' (Parameter types can be adVarChar,adDate,adInteger)
cmd.Parameters.Append cmd.CreateParameter("Assembly", adVarChar, adParamInput, 10, Range("B1").Text)
Application.StatusBar = "Running stored procedure..."
cmd.CommandText = "Custom.PRO_BOM_XXXX"
Set rs = cmd.Execute(, , adCmdStoredProc)
' Copy the results to cell B7 on the first Worksheet
Set WSP1 = Worksheets(1)
'
If rs.EOF then
Application.StatusBar = ""
GoTo Closedown
End If
Dim NumRows As Integer, EndRow As Integer, EndCol As Integer
EndCol = 12 ' You can adjust this
NumRows = rs.RecordCount
EndRow = 7 + NumRows ' - Adjust the number 7 if you ever decide to start pasting from 8
' Do the paste
WSP1.Cells(8, 2).CopyFromRecordset rs
' Now set the range:
Dim PastedRange As Range
With WSP1
Set PastedRange = .Range(.Cells(8, 2), .Cells(EndRow, EndCol))
End With
'
PastedRange.Borders.Color = vbBlack ' Thanks for the tip, sktneer
'
Application.StatusBar = "Data successfully updated."
Closedown:
rs.Close: Set rs = Nothing
Set cmd = Nothing
con.Close: Set con = Nothing
End Sub
Thanks to everyone for the help. Here's what I contrived for a working solution:
Sub Button1_Click()
Dim con As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim WSP1 As Worksheet
Set con = New ADODB.Connection
Set cmd = New ADODB.Command
Set rs = New ADODB.Recordset
Application.DisplayStatusBar = True
Application.StatusBar = "Contacting SQL Server..."
Set WSP1 = Worksheets(1)
WSP1.Activate
' Remove any values in the cells where we want to put our Stored Procedure's results.
Dim rngRange As Range
Set rngRange = Range(Cells(8, 2), Cells(Rows.Count, 1)).EntireRow
rngRange.ClearContents
rngRange.ClearFormats
' Log into our SQL Server, and run the Stored Procedure
con.Open "Provider=SQLOLEDB;Data Source=XXXXX;Initial Catalog=XXXXX;Integrated Security=SSPI;Trusted_Connection=Yes"
cmd.ActiveConnection = con
Application.StatusBar = "Running stored procedure..."
cmd.CommandText = "PRO_BOM_XXXXX"
Set rs = con.Execute("Exec Custom.PRO_XXXXX '" & ActiveSheet.Range("B1").Value2 & "','" & ActiveSheet.Range("B2").Value2 & "'")
' Copy the results to cell B7 on the first Worksheet
Set WSP1 = Worksheets(1)
If rs.EOF Then
Application.StatusBar = ""
GoTo Closedown
End If
Dim EndCol As Integer
EndCol = 14
WSP1.Cells(8, 2).CopyFromRecordset rs
'find the last row
Dim LastRow As Long
With ActiveSheet
LastRow = .Cells(.Rows.Count, 3).End(xlUp).Row
End With
' Now set the range:
Dim PastedRange As Range
With WSP1
Set PastedRange = .Range(.Cells(8, 2), .Cells(LastRow, EndCol))
End With
'Add borders
PastedRange.Borders.Color = vbBlack
Application.StatusBar = "Data successfully updated."
Closedown:
rs.Close: Set rs = Nothing
Set cmd = Nothing
con.Close: Set con = Nothing
End Sub

ADO functionality.. copy, filter, paste from closed workbook to active wrokbook

I am currently looking for an alternative to the solution below, but using the ADO functionality so that the source workbook isn't opened. I am imagining this will decrease processing time?
Your thoughts..
Thanks
Sub CopyFilteredValuesToActiveWorkbook()
Dim wbSource As Workbook, wbDest As Workbook
Dim wsSource As Worksheet, wsDest As Worksheet
Dim rngSource As Range, rngDest As Range
Set wbSource = Workbooks.Open("\\Linkstation\rrm\X_DO_NOT_TOUCH_CC\MasterLogFile\Masterlogfile.xlsx", , True) 'Readonly = True
Set wsSource = wbSource.Worksheets("LogData")
wsSource.Range("$A$1:$H$3").AutoFilter Field:=3, Criteria1:="Opera"
Set rngSource = wsSource.Range("A:Z")
Set wbDest = ThisWorkbook
Set wsDest = wbDest.Worksheets("MLF")
Set rngDest = wsDest.Range("A:Z")
rngDest.Value = rngSource.Value 'Copies values over only, if you need formatting etc we'll need to use something else
wbSource.Close (False) 'Close without saving changes
End Sub
You could use a reference to Active X Data Objects 6.0, to use SQL queries
Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adCmdText = &H1
Public Sub GetValues (path as String, destination as Range)
Dim conStr as String, strSQL as string
Dim con as new ADODB.Connection, rs as new ADODB.Recordset
conStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" & path & "';" & _
"Extended Properties=""Excel 12.0;HDR=YES;IMEX=1;"";"
strSQL = "SELECT * FROM [LogData$] WHERE [CriteriaColumn] = 'Opera'"
con.Open conStr
rs.open strSQL, con, adOpenStatic, adLockOptimistic, adCmdText
destination.CopyFromRecordset rs
rs.close
con.close
End Sub
Where the CriteriaColumn is the Header of the Column used as criteria to filter
You can call the subroutine as follows:
Dim path as string, rngDest as Range
path = "\\Linkstation\rrm\X_DO_NOT_TOUCH_CC\MasterLogFile\Masterlogfile.xlsx"
'The Upper left cell of the range that will receive the data:
Set rngDest = ThisWorkbook.Worksheets("MLF").Range("A1")
GetValues path, rngDest
You are missing this line:
Set rs = CreateObject("ADODB.Recordset")
For some reason Win XP will not run without it. It should be placed right after con.Open conStr.