Ok, so I have an Excel-file with data. This data comes from a query that has been manually copied from an Access database. Since this has to be done every day we want to make it automatically.
I already have VBA code inside the Access database that opens the query and writes it away into the Excel-file on the right sheet.
However, it works when I put a static range for the insert so it actually just overwrites the range I say:
Dim rst As DAO.Recordset
Dim ApXL As Object
Dim xlWBk As Object
Dim xlWSh As Object
Set rst = CurrentDb.OpenRecordset("Query name")
Set ApXL = CreateObject("Excel.Application")
ApXL.Application.ScreenUpdating = False
ApXL.Visible = True
Set xlWBk = ApXL.Workbooks.Open("C:\blabla.xlsm", True, False)
Set xlWSh = xlWBk.Worksheets(1)
xlWSh.Activate
xlWSh.range("A1341").CopyFromRecordset rst
xlWBk.Save
xlWBk.Close False
ApXL.Quit
rst.Close
Set rst = Nothing
Notice the xlWSh.range("A1341").CopyFromRecordset rst.
It just pastes the query from this row because I know this is the first empty row.
I already tried lots of other codes but I always get errors:
TheLastRow = ActiveSheet.UsedRange.SpecialCells(xlCellTypeLastCell).Row
=> Error 424: Object required
Dim MyRange As range
Dim lngLastRow As Long
Set MyRange = xlWSh.range(strColum & "1")
lngLastRow = xlWSh.Cells(65536, MyRange.Column).End(xlUp).Row
=> Compilation-error on Dim MyRange As range: user-defined type not defined
Dim MyRange As Object
Dim lngLastRow As Long
Set MyRange = xlWSh.range(strColum & "1")
lngLastRow = xlWSh.Cells(65536, MyRange.Column).End(xlUp).Row
=> Error 1004: Application-defined or object-defined error
With xlWBk.Sheets("Sheetname")
lastrow = .range("A" & .Rows.Count).End(xlUp).Row
=> Error 1004: Application-defined or object-defined error
End With
With xlWSh
lastrow = .Cells.Find(What:="*", After:=.range("A1"), SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
=> Error 9: Subscript out of range
End With
So I have no idea anymore what to do.
The only other option is by reading the entire sheet into the Access database as a List or Array or Table and then do a .Count or something but inserting into lastRow+1 or firstEmptyRow should be quicker, doable and much easier to program.
Thanks in advance!
The problem is that Access doesn't know anything about Excel constants, such as xlUp, xlByRows and so on (until you add reference to excel library).
There are to ways for you:
1) Go to TOOLS->REFERENCES and add reference to Microsoft Excel 1x.0 Object Library (version may vary)
2) change all excel constants to their values (e.g. change SearchOrder:=xlByRows to SearchOrder:=1 and so on):
xlUp equals to -4162
xlByRows eqals to 1
xlPrevious eqals to 2
xlCellTypeLastCell equals to 11
Here is link with values of excel constants: xlConstants (or another way to determine constants values - is to use this line in EXCEL VBA : MsgBox xlCellTypeLastCell)
Related
I am new to VBA and macros.
I got the repeated task of copy data from Excel and paste it in a particular location in the word document.
For example, my excel sheet has the data like this:
Col1
Col2
ID_1
I'm_One
ID_2
I'm_Two
ID_3
I'm_Three
Now i'm looking for a Word macro
Get text in Word table with cell position 3
Find the same text in Excel Col1
Get the value of Col2 from Excel
Paste the value of Col2 in word table with cell position 10
Repeat the same process for another table in Word document
[Update]
I have tried with multiple code snippets by google search but unable to construct the working macro.
Sub pull_from_Excel2()
'ref: https://www.macworld.com/article/211753/excelwordvisualbasic.html
Dim Month As String
ID_Range = "A2:A6" 'Select this as range like "A2:A16"
Offset_to_fetch = 1 'Select this to fetch comments etc. value starts with
Set xlSheet = GetObject("D:\Excel.xlsx")
'Snippets:
'Debug.Print VarType(xlSheet.Worksheets("Sheet1").Range("A3:A5").Value)
'8204
Dim Cell As Range, rng As Range
Debug.Print VarType(xlSheet.Worksheets("Sheet1").Range(ID_Range).Value2)
Set rng = xlSheet.Worksheets(1).Range(ID_Range)
For Each Cell In rng
Debug.Print Cell.Text
Next Cell
End Sub
I used this url to construct my skeleton code: https://www.macworld.com/article/211753/excelwordvisualbasic.html
When i try to get the values from the range of cells in excel, i got the following error for the code.
Set rng = xlSheet.Worksheets(1).Range(ID_Range).Value2
The above line gives "Object required" error when running.
Set rng = xlSheet.Worksheets(1).Range(ID_Range)
The above line gives "Type Mismatch" error when running.
Notes: For this error, I tried to use for each loop as this is array but the error is showing before executing the for loop.
Kindly assist.
I recommend to use Option Explicit and declare all your varibales properly. This way it is less likely that you end up with unseen errors.
To activate it for all new codes that you add in the future, you can activate it directly in Excel and Word. This is a good practice and will protect you from doing it wrong by notifying you of not declared variables:
In the VBA editor go to Tools › Options › Require Variable Declaration.
This will add Option Explicit to new modules only. In existing modules Option Explicit needs to be added manually as first line.
Further I highly recommend to name your variables according what they contain because otherwise it gets very confusing. You named your variable xlSheet but you load a workbook into it and not a worksheet.
The next issue is that your code is in Word and if you declare rng As Range then this is of type Word.Range and not Excel.Range and those are diffetent types so that is why you get a "Type Mismatch" error.
To solve this you either go in Word VBA to Extras › Refereces … and set a reference to the Excel library so you can declare your variable Dim xlRng As Excel.Range or if you don't set a reference you declare it as Object or Variant like in below example:
' This code is in Word!
Option Explicit
Public Sub pull_from_Excel2()
'declare constants
Const ID_Range As Sting = "A2:A6" 'Select this as range like "A2:A16"
Const Offset_to_fetch As Long = 1 'Select this to fetch comments etc. value starts with
Dim xlWorkbook As Object
Set xlWorkbook = GetObject("D:\Excel.xlsx") 'This expects the Excel to be already open! If not open you need to use CreateObject("Excel.Application")
Dim xlRng As Object
Set xlRng = xlWorkbook.Worksheets(1).Range(ID_Range)
Dim xlCell As Object
For Each xlCell In xlRng
Debug.Print xlCell.Text
Next xlCell
End Sub
Note if your workbook Set xlWorkbook = GetObject("D:\Excel.xlsx") is not open in Excel you need to use CreateObject("Excel.Application") and open it.
Dim xlApp As Object
Set xlApp = CreateObject("Excel.Application")
Dim xlWorkbook As Object
Set xlWorkbook = xlApp.Workbooks.Open(FileName:="D:\Excel.xlsx") 'will open the workbook
xlApp.Visible = True 'make it false to open Excel invisible in the background
'your code here …
'in the end close workbook and Excel (espaciall if you had it invisible!)
xlWorkbook.Close SaveChanges:=False
xlApp.Quit 'close Excel
Option Explicit
Sub UpdateTables()
Const XLSX = "D:\Excel.xlsx"
Dim xlApp, wb, ws
Dim rngSearch, rngFound
Dim iLastRow As Long, n As Integer
' open spreadsheet
'Set xlApp = New Excel.Application
Set xlApp = CreateObject("Excel.Application")
xlApp.Visible = True
Set wb = xlApp.Workbooks.Open(XLSX, 1, 1)
Set ws = wb.Sheets(1)
iLastRow = ws.Cells(ws.Rows.Count, "A").End(-4162).Row 'xlUp
Set rngSearch = ws.Range("A2:A" & iLastRow)
' update tables
Dim doc As Document, tbl As Table, s As String
Set doc = ThisDocument
For Each tbl In doc.Tables
s = tbl.Cell(1, 1).Range.Text
s = Left(s, Len(s) - 2)
Set rngFound = rngSearch.Find(s, LookIn:=-4163, LookAt:=1) ' xlValues, xlWhole
If rngFound Is Nothing Then
MsgBox "'" & s & "' not found in table " & tbl.Title, vbExclamation
Else
tbl.Range.Cells(3).Range.Text = rngFound.Offset(0, 1)
n = n + 1
End If
Next
wb.Close False
xlApp.Quit
MsgBox n & " tables updated", vbInformation
End Sub
I want to resize a chart table in PowerPoint via VBA. I've read the following solution multiple times (Resize Listobject Table dynamically with VBA) and it does seem precisely what I need, but for some reason (maybe because I'm running the macro from PowerPoint) it gives me the following error: Automation error (Error 440).
I plan to use the Resize method because I'm updating a PPT chart data table from another Excel file without using the .Activate method (I opted to not use the .Activate because it opened many charts workbooks after the Macro finished execution, even with multiple Waits and Excel.Application.Quit and .Close).
It works great, the charts workbooks do not flash on the screen and the values are copied fast, BUT... the table size is not correct. It only includes the 1st line of the ppt chart data table, and thus my chart is rendered incomplete.
Dim Line As Range Dim financialPartner As String, financialProject As String
financialPartner = excl.Workbooks("HNK-Status-CDAU.xlsx").Sheets("Financial").Cells(int_lin, 2)
financialProject = excl.Workbooks("HNK-Status-CDAU.xlsx").Sheets("Financial").Cells(int_lin, 3)
Dim found As Boolean
found = False
Dim lastRow As Long
Dim financialChart As Chart
Dim financialChartData As Range
Dim financialChartTable As ListObject
Dim financialChartTablews As Worksheet
lastRow = ActiveWindow.Selection.SlideRange.Shapes("RevenuesVolume").Chart.chartData.Workbook.Sheets(1).Range("A1048576").End(xlUp).Row
Set financialChart = ActiveWindow.Selection.SlideRange.Shapes("RevenuesVolume").Chart
Set financialChartTablews = ActiveWindow.Selection.SlideRange.Shapes("RevenuesVolume").Chart.chartData.Workbook.Worksheets(1)
Set financialChartTable = financialChartTablews.ListObjects("Tabela1")
For Each Line In chartDataTable.DataBodyRange.Rows
Dim lineNumber As Long
lineNumber = Line.Row
If ((Line.Columns(1) <> financialPartner) Or (Line.Columns(2) <> financialProject)) And found Then
Exit For
End If
If (Line.Columns(1) = financialPartner) And (Line.Columns(2) = financialProject) Then
found = True
With financialChart.chartData
Set financialChartData = .Workbook.Worksheets(1).ListObjects(1).Range
financialChartData.Range("A" & lastRow).Value = chartDataWs.Cells(lineNumber, 4)
financialChartData.Range("B" & lastRow).Value = chartDataWs.Cells(lineNumber, 5)
financialChartData.Range("C" & lastRow).Value = chartDataWs.Cells(lineNumber, 6)
lastRow = lastRow + 1
financialChartTable.Resize Range("A1:C" & lastRow)
.Workbook.Close
End With
End If
Next
Next
you all were a great help with my last issue, so I figured Id ask another question. I am currently creating a code that keeps track of a mailroom's inventory. The code that I am working on is a textbox that whenever something is typed, it copies the value to the excel and it triggers an advanced search. I want to use xlfiltercopy to prevent visual damage to the excel sheet and so it is easier to update the listbox in the userform with the filtered information. Please let me know if you can find a reason that the error "AdvancedFilter method of Range class failed"
EDIT: If possible, I would like to email the entire excel to someone to see if the program works on another computer. I cannot physically think of a way to get it to work. Please consider it!
' Input on the 2nd page
' This code will update the list box below automatically as you type a name
Private Sub TextBox5_Change()
If Me.TextBox5.Value = "" Then
Exit Sub
End If
Dim wks As Worksheet
Set wks = ThisWorkbook.Sheets("Mail_Inventory")
Dim rgData As Range
Dim rgCriteria As Range
Dim rgOutput As Range
Dim currentinventory As Long
Dim filteredcurrent As Long
Dim temp As Long
temp = wks.Range("AS1").Value
If temp > 0 Then
wks.ListObjects("CurrentFiltered").DataBodyRange.Rows.Delete
End If
wks.Range("AP6").Value = Me.TextBox5.Value
currentinventory = wks.Range("A1").Value
'Set rgData = ThisWorkbook.Worksheets("Mail_Inventory").Range("A2:H" & currentinventory + 2)
'Set rgCriteria = ThisWorkbook.Worksheets("Mail_Inventory").Range("AP5:AP6")
'Set rgOutput = ThisWorkbook.Worksheets("Mail_Inventory").Range("AS2:AZ2")
Set rgData = Range("A2:H" & currentinventory + 2)
Set rgCriteria = Range("AP5:AP6")
Set rgOutput = Range("AS2:AZ2")
rgData.AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=rgCriteria, CopytoRange:=rgOutput
'wks.Range("A2:H" & currentinventory + 2).AdvancedFilter Action:=xlFilterCopy, CriteriaRange:=wks.Range("AP5:AP6"), CopyToRange:=wks.Range("AS2:AZ2")
'filteredcurrent = wks.Range("AS1").Value
'Me.ListBox2.Clear
'Me.ListBox2.RowSource = wks.Range("AS2:AV" & filteredcurrent + 2)
I have a working Outlook macro which exports the task list of the current user to an Excel spreadsheet, but I want to change it to use late binding for ease of distribution (ie I don't have to explain to other users about setting a library reference etc.)
I followed the example Convert Early Binding VBA to Late Binding VBA : Excel to Outlook Contacts to set my Excel variables as objects.
Below is a comparison of how i declared the variables pre/post binding change:
'Late binding variables and their early binding equivilants
Dim objExcel As Object 'Dim objExcel As New Excel.Application
Dim exWB As Object 'Dim exWb As Excel.Workbook
Dim sht As Object 'Dim sht As Excel.Worksheet
Dim Range As Object 'Dim Range As Excel.Range
Dim r As Object 'Dim r As Range
Dim cell As Object 'Dim cell As Range
'set application
Set objExcel = CreateObject("Excel.Application")
I am now getting a runtime 1004 error in the following section of my code:
With objExcel.ActiveSheet
Set r = .Range(.Cells(2, col), .Cells(.Rows.Count, col).End(xlUp)) 'runtime 1004 error here after late binding modification
End With
For Each cell In r
s = cell.Text
If Len(Trim(s)) > 0 Then
iloc = InStr(1, s, sChar, vbTextCompare)
If iloc > 1 Then
s1 = Left(s, iloc - 1)
cell.Value = s1
Else
If iloc <> 0 Then
cell.ClearContents
End If
End If
End If
Next cell
y = y + 1
stat_string = ""
End If
Next x
'Autofit all column widths
For Each sht In objExcel.ActiveWorkbook.Worksheets
sht.Columns("A").EntireColumn.AutoFit
sht.Columns("B").EntireColumn.AutoFit
sht.Columns("C").EntireColumn.AutoFit
sht.Columns("D").EntireColumn.AutoFit
sht.Columns("E").EntireColumn.AutoFit
sht.Columns("F").EntireColumn.AutoFit
Next sht
exWB.Save
exWB.Close
Set exWB = Nothing
'this kills the excel program from the task manager so the code will not double up on opening the application
'sKillExcel = "TASKKILL /F /IM Excel.exe"
'Shell sKillExcel, vbHide
objExcel.Application.Quit
I have included the rest of the code after the error line so, if there are further run-time problems, they might be picked up by the incredible people on SO.
I'm assuming that the methodology for declaring my "Range" is incorrect, but I am not really sure why, and therefore unsure on how to fix it.
Any body out there with a suggestion?
Thanks!
xlUp is an Excel constant that is defined in the Excel library. If you have removed the reference, then xlUp will be an undeclared variable.
If you have Option Explicit set, then you should find that when compiling.
I would like to find a string in an Excel worksheet. The Excel cell values are calculated using formulas. When I run this code:
Set firstExcel = CreateObject("Excel.application")
firstExcel.Workbooks.Open "C:\Myroute\excelName.xls"
Set oSht = firstExcel.Worksheets("Input Data")
str="hello"
Set aCell = oSht.Range("A1:E15").Find(str, , xlValues)
MsgBox aCell.row
I have an error that says:
Error: Subscript out of range
Code: 800A0009
The reason you get the error message on the .Find line is that vbscript does not recognize Excels constants, so you need to replace xlValues with the number -4163. (All Excel constant values can be found in the VBA Object Browser).
Also, the line you wrote Set oSht = firstExcel.Worksheets("Input Data") does not make sense to VB because firstExcel is the Excel Application itself and there is no Worksheet object associated with the Excel Application itself, but there is within the Workbook object.
Set firstExcel = CreateObject("Excel.application")
Set wkb = firstExcel.Workbooks.Open("C:\Myroute\excelName.xls")
Set oSht = wkb.Worksheets("Input Data")
str="hello"
Set aCell = oSht.Range("A1:E15").Find(str,,-4163)
If Not aCell is Nothing Then MsgBox aCell.row 'because if it does not find the string, it will not return a range object
Furthermore you could declare a constant at the top of your code and use that constant in the .Find statement.
const xlValues = -4163
.Find(str,,xlValues)