Get number of row records - vba

I would like to append data using word as front-end userform and export the data to specific csv file when submit button is clicked.
While firstly I need to know which row I should append the data. Here is the following code and I got error message for nrow = rng1.UsedRange.Rows.Count lines
'Reference - Microsoft Excel 12.0 Object library 12
'Word
Global objDoc As word.Document
Global docName As String
Global docPath As String
Global docFullName As String
'Workbook
Global objWb As Excel.Workbook
Global objWs As Excel.Worksheet
Global rng1 As Range
Global nrow As Integer
'Global objWord As word.Application
Public Sub Initial_Global()
'Word
Set objDoc = ActiveDocument
docName = objDoc.Name
docPath = objDoc.Path
docFullName = objDoc.FullName
'Excel
Set objWb = Workbooks.Open(FileName:="C:\Users\1502911\Desktop\Database1.csv")
Set objWs = objWb.Worksheets("Database1")
Set rng1 = objWs.Range("A1")
nrow = rng1.UsedRange.Rows.Count
MsgBox nrow
End Sub

nrow = rng1.UsedRange.Rows.Count
this means:
Worksheets("Database1").Range("A1").UsedRange.Rows.Count 'wrong
of course it will return error, because you asking the used range of the range "A1"
must be like this:
Worksheets("Database1").UsedRange.Rows.Count
so in your code, if you required to count only rows in used range of the column "A" must be the next:
nrow = objWs.UsedRange.Columns(1).Rows.Count
but be carefull with this method of the getting the last row in sheet, the problem will apear when the used range will not start from the first row, e.g. if the first row will be empty then you will recieve count less then expected. in this case use this method:
nrow = objWs.Cells(Rows.Count, 1).End(xlUp).Row
also can be the problem, when e.g. count of the used cells in column "A" less by the some reason than count of the used cells in Columns "B" or "D " etc. but you need to get the last non-used row, in this case you need this method:
Dim ocell As Range
For Each ocell In objWs.UsedRange
nrow = ocell.Row
Next
MsgBox nrow

Related

How can I look in one worksheet and copy and paste into another workbook based off criteria from another worksheet?

Good Morning.
I have a workbook with multiple worksheets in it. Lets say worksheet A & B
In worksheet B I have multiple supplier columns some of them have X's in them and some of them don't
What I would like to know how to do is to be if there is an "X" present in the column then look to the leftmost Column (A) and look for that part number in Worksheet A.
When it finds the part number in Worksheet A, I would like to copy all of the rows and columns associated with it and paste it into a brand new workbook.
Typically the part number is showing on multiple rows let's say rows 1-6 and the information I'd like to copy spans across multiple columns Let's say to Column "T".
Your question is not to clear.
Assuming that you mean you have one workbook with a worksheet named A and a worksheet named B, the algorithm you describe is something like this:
Sub Test()
Dim wb as Workbook
Dim wsA as Worksheet
Dim wsB as Worksheet
Dim suppliersRange as Range
Dim xRange as Range
Dim searchValue as string
Dim foundRange as Range
'The two worksheets in the initial book:
Set wsA = ThisWorkbook.Worksheets("A")
Set wsB = ThisWorkbook.Worksheets("B")
'The supplier column to search:
Set suppliersRange = wsB.Range("D:D") 'let's assume it column D for now.
Set xRange = suppliersRange.Find("X") 'Find "X"
If not xRange is nothing then
searchValue = wsB.Range("A" & xRange.Row).value 'Get the value from column A to do the next search
End If
Set foundRange = wsA.UsedRange.Find(searchValue) 'Search for this number that we got with the previous step.
If not foundRange is nothing then 'If it's found
Set wb = Workbooks.Add 'Create a new workbook
wsA.UsedRange.Copy wb.Worksheets(1).Range("A1") 'And copy Sheet A in there
End If
Set foundRange = Nothing
Set xRange = Nothing
Set suppliersRange = Nothing
Set wsA = Nothing
Set wsB = Nothing
Set wb = Nothing
End Sub
Note that since you do not specify what you mean with "multiple rows for a part" and/or what columns, etc. - I just copy the entire sheet contents. Of course you can filter out the actual range to copy, but this code for sure does the searches for you, creates the new workbook and copy-pastes from your Sheet A.

Outlook VBA find last Row in Excel Worksheet

I'm writing a function in Outlook VBA that involves reading content from an excel workbook.
The part I'm struggling with is finding the last row in a column (column A in this example). While the 1st line in the highlighted block correctly displays the content of A1 cell in given worksheet, the second line gives a Error "424" - object required.
Any suggestions into the problem would be greatly appreciated.
Public Function openExcel()
Dim xlApp As Object
Dim sourceWorkBook
Dim sourceWorkSheet
Dim cellVal As String
Dim lastRow As Long
Set xlApp = CreateObject("Excel.Application")
With xlApp
.Visible = True
.EnableEvents = True
End With
Set sourceWorkBook = xlApp.Workbooks.Open("C:\SAMPLEPATH\Template.xlsx")
Set sourceWorkSheet = sourceWorkBook.Worksheets("Sheet1")
sourceWorkBook.Activate
With Activesheet
cellVal = sourceWorkSheet.Cells(1, 1)
lastRow = sourceWorkSheet.Cells(.Rows.Count, "A").End(xlUp).Row
End With
sourceWorkBook.Save
sourceWorkBook.Close
xlApp.Quit
End Function
If you want to have the ability to use Excel constants within your code, you will need to either
a) Include a reference to a Microsoft Excel Object Library, or
b) Create your own constant, e.g.
End(-4162)
or
Const xlUp As Long = -4162
...
... End(xlUp)

Using Word VBA to automate Excel, I get Run-time error '13': Type mismatch when using the .Find function

I'm trying to get data from an excel sheet to a word document. I try using the 'Find' function however I keep getting the same error "Type mismatch" on this line:
Set FoundRange = .Cells.Find(260707)
Here is the subroutine I am running.
Sub GetID()
Dim oXL As Object
Dim oWB As Object
Dim oSheet As Object
Dim WorkbookToWorkOn As String
Dim FoundRange As Range
Dim dummyvar As String
'Start a new instance of Excel
Set oXL = CreateObject("Excel.Application")
'Line to make Excel Visible or not
oXL.Visible = False
'Open the workbook
'Set the file path to access the 'Certified Personnel' table
WorkbookToWorkOn = "\\DataSource\CertifiedPersonnel.xlsx"
Set oWB = oXL.Workbooks.Open(FileName:=WorkbookToWorkOn, ReadOnly:=True, IgnoreReadOnlyRecommended:=True)
Set oSheet = oXL.ActiveWorkbook.Sheets("tblCertifiedPersonnel")
'End of Excel Automation. Everything from this point on can reference Excel.
With oSheet
dummyvar = .Cells(1, 2).Text
.Cells(1, 2).Select
'Set the range of the cell containing the ID number
'If the ID was found
Set FoundRange = .Cells.Find(260707)
If Not FoundRange Is Nothing Then
'Set the NTlogin equal to the value of column 1, and row corresponding to the FoundRange row
NTlogin = .Cells(FoundRange.Rows, 1).Text
Role = .Cells(FoundRange.Rows, 4).Text
End If
End With
'End Excel reference
oXL.ActiveWorkbook.Close SaveChanges:=False
oXL.Application.Quit
Set oXL = Nothing
Set oWB = Nothing
Set oSheet = Nothing
End Sub
I know it is accessing the correct workbook, because the dummy variable (dummyvar) is returning the value I expect. I have tried several things related to the 'Find' function, however I have not been able to get it to work. Any ideas? Much appreciated.
You are using late binding and have FoundRange declared as a Range. Since this is in a Word document, you're implicitly declaring it as a Word.Range here:
Dim FoundRange As Range
.Find is returning an Excel.Range. Change it to:
Dim FoundRange As Object
With the assumption that the ID values are stored as text in the worksheet, either with a cell type of Text or with an apostrophe/single-quote in front of the number, you may need to format the ID as string. With the further assumption that eventually you may want to pass the ID via parameter to the procedure, give this a try:
Set FoundRange = .Cells.Find(CStr(260707))
That will also allow you to replace the constant number with a variable if desired.

Copy the value from a cell in a worksheet into a range of cells

I'm intending to conduct a macro which will open up a workbook from the specified path, and loop through its worksheets which has the names "Januari, Februari, Mars" specifically, to deduct the value from C34. C34 has a value recorded there every time, so it shouldn't change. However I want to copy it to the current worksheet, where the first target should be at AA73, the second at AA74 etc. My code is
Sub Test()
Dim myHeadings
Dim i As Long
Dim path As String
path = "C:\pathtofile\file.xlsx"
Dim currentWb As Workbook
Set currentWb = ActiveWorkbook
Dim openWb As Workbook
Set openWb = Workbooks.Open(path)
Dim openWs As Worksheet
myHeadings = Array("Januari", "Februari", "Mars")
For i = 0 To UBound(myHeadings)
Set openWs = openWb.Sheets("&i")
currentWb.Sheets("Indata").Range("AA73+Application.Match(i,Array,False)").Value = openWs.Range("C34").Value
Next i
End Sub
However the compiler says that the subscript is out of range at the row with
Set openWs = openWb.Sheets("&i")
Here I've tried to do "i", i, &i among other things, but it haven't changed. Also I've tried to use "ThisWorkbook" instead of "ActiveWorkbook" but it didn't help either. Does anybody have an input as to how to achieve this in a more proper way?
EDIT: Adapting to the response from Dave, it works to import the sheets. However I get an error in:
currentWb.Sheets("Indata").Range("AA73+Application.Match(i,Array,False)").Value = openWs.Range("C34").Value
Where I get Automation Error -2147221080 (800401a8) at said code snippet.
You have already put your sheet names into an array, so you can just call the sheet name from the array as:
Set openWs = openWb.Sheets(myHeadings(i))

Use VBA functions and variables in a spreadsheet

I'm new to Excel VBA. I am trying to use a VBA function I found online that enables the user to use goalseek on multiple cells at a time. How do I call the function in a spreadsheet and how do I point to the cells that are supposed to be associated with the variables in the function (e.g. Taddr, Aaddr, gval). Do I have to write the cell values and ranges in the code itself and just run it that way?
Maybe I should redefine the function so that it takes these variables as input, so I can write a formula like =GSeekA(Taddr,Aaddr,gval)
Option Explicit
Sub GSeekA()
Dim ARange As Range, TRange As Range, Aaddr As String, Taddr As String, NumEq As Long, i As Long, j As Long
Dim TSheet As String, ASheet As String, NumRows As Long, NumCols As Long
Dim GVal As Double, Acell As Range, TCell As Range, Orient As String
' Create the following names in the back-solver worksheet:
' Taddr - Cell with the address of the target range
' Aaddr - Cell with the address of the range to be adjusted
' gval - the "goal" value
' To reference ranges on different sheets also add:
' TSheet - Cell with the sheet name of the target range
' ASheet - Cell with the sheet name of the range to be adjusted
Aaddr = Range("aaddr").Value
Taddr = Range("taddr").Value
On Error GoTo NoSheetNames
ASheet = Range("asheet").Value
TSheet = Range("tsheet").Value
NoSheetNames:
On Error GoTo ExitSub
If ASheet = Empty Or TSheet = Empty Then
Set ARange = Range(Aaddr)
Set TRange = Range(Taddr)
Else
Set ARange = Worksheets(ASheet).Range(Aaddr)
Set TRange = Worksheets(TSheet).Range(Taddr)
End If
NumRows = ARange.Rows.Count
NumCols = ARange.Columns.Count
GVal = Range("gval").Value
For j = 1 To NumCols
For i = 1 To NumRows
TRange.Cells(i, j).GoalSeek Goal:=GVal, ChangingCell:=ARange.Cells(i, j)
Next i
Next j
ExitSub:
End Sub
GSeekA is a Subprocedure, not a Function. Subprocedures cannot be called from worksheet cells like Functions can. And you don't want to convert GSeekA into a function. Functions should be used to return values to the cell(s) from which they're called. They shouldn't (and often can't) change other things on the sheet.
You need to run GSeekA as a sub. Now the problem becomes how you get user provided information into the sub. You can use InputBox to prompt the user to enter one piece of information. If you have too many, InputBox becomes cumbersome.
You can create areas in the spreadsheet where the user must enter information, then read from that area. That's how it's set up now. It's reading cells named asheet and tsheet. As long as those named ranges are present, the code works.
Finally, you can create a UserForm that the user will fill out. That's like putting a bunch of InputBoxes on one form.
Update Here's a simple procedure that you can start with and enhance.
Public Sub GSeekA()
Dim rAdjust As Range
Dim rTarget As Range
Dim dGoal As Double
Dim i As Long
'Set these three lines to what you want
Set rAdjust = Sheet1.Range("I2:I322")
Set rTarget = Sheet1.Range("J2:J322")
dGoal = 12.1
For i = 1 To rAdjust.Count
rTarget.Cells(i).GoalSeek dGoal, rAdjust.Cells(i)
Next i
End Sub