I'm having some trouble with looping and creating MS Excel docs, code snippet below
Private Sub selectedRowsButton_Click( _
ByVal sender As Object, ByVal e As System.EventArgs) _
Handles selectedRowsButton.Click
Dim selectedRowCount As Integer = _
DataGridView1.Rows.GetRowCount(DataGridViewElementStates.Selected)
If selectedRowCount > 0 Then
Dim sb As New System.Text.StringBuilder()
Dim objexcel As New Excel.Application
Dim i As Integer
Dim FACode As Integer
Dim Sitename As Integer
Dim Sitecode As Integer
Dim Address As Integer
Dim City As Integer
Dim State As Integer
Dim ZIP As Integer
FACode = 1
Sitename = 5
Sitecode = 2
Address = 6
City = 7
State = 9
ZIP = 10
Dim xlWorkbook As Excel.Workbook
xlWorkbook = objexcel.Workbooks.Open("template path")
For i = 0 To selectedRowCount - 1
objexcel.Visible = True
objexcel.Range("B2").Value = DataGridView1.SelectedCells(Sitename).Value.ToString()
objexcel.Range("B3").Value = DataGridView1.SelectedCells(Sitecode).Value.ToString()
objexcel.Range("B5").Value = DataGridView1.SelectedCells(FACode).Value.ToString()
Dim thisfile As Object
thisfile = objexcel.Range("B5").Value & "." & _
objexcel.Range("B3").Value & "." & "otherstring" & "." & "otherstring2" & "." & ".xls"
With objexcel
xlWorkbook.SaveAs(Filename:="c:\test\" & thisfile)
'~~> Close the Excel file without saving
xlWorkbook.Close(False)
End With
Next i
End If
I'm getting the error Exception from HRESULT: 0x800A03EC for the statement
objexcel.Range("B2").Value = DataGridView1.SelectedCells(Sitename).Value.ToString()
IF I select only one row of my DataGrid before creating the program works fine, it is when I select multiple rows that this error occurs. Since I'm creating the program specifically for multiple row selections I'm stumped as to where I've gone wrong. Any help or pointers appreciated, Thanks!
Two things
You have declared objexcel As Excel.Application so you shouldn't use objexcel.Range("B2").Value. Use xlWorkbook.Range("B2").Value. Change it everywhere in your code.
You cannot use SaveAs like that. See the snapshot below. If you want to save as xls file then you have to use FileFormat:=56
See this code example
'~~> Save As file
xlWorkbook.SaveAs(Filename:="c:\test\" & thisfile, FileFormat:=56)
If you do not specify the file format then you will get an error message when you open the file after opening.
You might want to look at this link on how to automate Excel from VB.Net
Topic: VB.NET and Excel
Link: http://www.siddharthrout.com/vb-dot-net-and-excel/
I am not too sure what you exactly are trying to do with the DGV. Like Sean mentioned you are not incrementing the values. If you can post a snapshot of how your DGV looks and how your Excel file should look after the export then we can help you in a much better way :)
Related
I am trying to filter a worksheet (via Column DL). I then need to insert a formula into Column DQ but only for the visible cells. I was previously using the code below which works except I do not want the specific reference to cell DQ3. This cell can change and thus the wrong formula is copied and pasted.
Dim LastRow As Long
Dim FinalRow As Long
LastRow = Range("B" & Rows.Count).End(xlUp).Row
Range("DL2:DL" & LastRow).AutoFilter Field:=116, Criteria1:= _
"ABC"
Range("DQ3").Copy
FinalRow = Cells(Rows.Count, "B").End(xlUp).Row
Range("DQ3:DQ" & FinalRow).Select
ActiveSheet.Paste
I tried the code below but it returns a "Run-time error '1004': Application-defined or object-defined error on the final line of code:
Dim LastRow As Long
Dim FinalRow As Long
LastRow = Range("B" & Rows.Count).End(xlUp).Row
Range("DL2:DL" & LastRow).AutoFilter Field:=116, Criteria1:= _
"ABC"
FinalRow = Range("B" & Rows.Count).End(xlUp).Row
Range("DQ2:DQ" & FinalRow).FormulaR1C1 = "=(RC[-1]-RC[-2])"
I also tried this code:
Dim LastRow As Long
Dim FinalRow As Long
LastRow = Range("B" & Rows.Count).End(xlUp).Row
Range("DL2:DL" & LastRow).AutoFilter Field:=116, Criteria1:= _
"ABC"
FinalRow = Range("B" & Rows.Count).End(xlUp).Row
Set RNG = Range("DQ2:DQ" & FinalRow).SpecialCells(xlCellTypeVisible)
RNG = "=(RC[-1]-RC[-2])"
This runs without any errors but does not fill any data into Column DQ.
Any suggestions on how to get rid of the error or how to achieve my original goal? I am not sure what I am trying will even work but this is where I got stuck.
Thanks!
I was able to achieve my goal using the code below. Posting in case someone else has the same issue in the future.
With ActiveSheet.Range("DQ2:DQ" & Cells(Rows.Count,2).End(xlUp).Row).SpecialCells(xlCellTypeVisible)
.Cells.FormulaR1C1 = "=((RC[-1]-RC[-2])"`
.Cells.FillDown`
Worksheets("WorksheetName").Columns(10).Calculate
End With
Cheers!
This is my script which opens Excel files and takes info from some cells then inserts it in another Excel document. I have included the entire script but marked where I think the error is. I am really confused at why this isn't working as I am using the exact same method in another script that works perfectly.
updated code from answers, same problem remains.
I think it's being caused by the Find_Excel_Row.
I tried putting the script in the function in the loop so there was no problem with variables but I got the same error.
Dim FSO 'File system Object
Dim folderName 'Folder Name
Dim FullPath 'FullPath
Dim TFolder 'Target folder name
Dim TFile 'Target file name
Dim TFileC 'Target file count
Dim oExcel 'The Excel Object
Dim oBook1 'The Excel Spreadsheet object
Dim oBook2
Dim oSheet 'The Excel sheet object
Dim StrXLfile 'Excel file for recording results
Dim bXLReadOnly 'True if the Excel spreadsheet has opened read-only
Dim strSheet1 'The name of the first Excel sheet
Dim r, c 'row, column for spreadsheet
Dim bFilled 'True if Excel cell is not empty
Dim iRow1 'the row with lower number in Excel binary search
Dim iRow2 'the row with higher number in Excel binary search
Dim iNumpasses 'Number of times through the loop in Excel search
Dim Stock 'product stock levels
Dim ID 'product ID
Dim Target 'Target file
Dim Cx 'Counter
Dim Cxx 'Counter 2
Dim RR, WR 'Read and Write Row
Call Init
Sub Init
Set FSO = CreateObject("Scripting.FileSystemObject")
FullPath = FSO.GetAbsolutePathName(folderName)
Set oExcel = CreateObject("Excel.Application")
Target2 = CStr("D:\Extractor\Results\Data.xls")
Set oBook2 = oExcel.Workbooks.Open(Target2)
TFolder = InputBox ("Target folder")
TFile = InputBox ("Target file")
TFileC = InputBox ("Target file count")
Call Read_Write
End Sub
Sub Read_Write
RR = 6
PC = 25
For Cx = 1 to Cint(TFileC)
Target = CStr("D:\Extractor\Results\"& TFolder & "\"& TFile & Cx &".html")
For Cxx = 1 to PC
Call Find_Excel_Row
Set oBook1 = oExcel.Workbooks.Open(Target)
Set Stock = oExcel.Cells(RR,5)
Set ID = oExcel.Cells(RR,3)
MsgBox ( Cxx &"/25 " &" RR: "& RR & " ID: " & ID & " Stock: " & Stock )
oBook1.Close
MsgBox "Writing Table"
oExcel.Cells(r,4).value = Stock '<<< Area of issue
oExcel.Cells(r,2).value = ID '<<<
oBook2.Save
oBook2.Close
Cxx = Cxx + 1
RR = RR + 1
Next
Cx = Cx + 1
Next
MsgBox "End"
oExcel.Quit
End sub
Sub Find_Excel_Row
bfilled = False
iNumPasses = 0
c = 1
iRow1 = 2
iRow2 = 10000
Set oSheet = oBook2.Worksheets.Item("Sheet1")
'binary search between iRow1 and iRow2
Do While (((irow2 - irow1)>3) And (iNumPasses < 16))
'Set current row
r = Round(((iRow1 + iRow2) / 2),0)
'Find out if the current row is blank
If oSheet.Cells(r,c).Value = "" Then
iRow2 = r + 1
Else
iRow1 = r - 1
End If
iNumPasses = iNumPasses + 1
Loop
r = r + 1
'Step search beyond the point found above
While bFilled = False
If oSheet.Cells(r,c).Value = "" Then
bFilled = True
Else
r = r + 1
End If
Wend
oExcel.Workbooks.Close
End Sub
In addition to what #Ekkehard.Horner said, you can't use the Excel object after quitting, so you should be getting an error when trying to open Data.xls.
oExcel.Workbooks.Close
oExcel.Quit
'writes to Graph sheet
set oBook = oExcel.Workbooks.Open("D:\Extractor\Results\Data.xls")
' ^^^^^^ This should be giving you an error
'Writing Table
MsgBox "Writing Table"
oExcel.Cells(r,4).value = Stock <<< Error here
oExcel.Cells(r,2).value = ID <<<
In fact, you're closing the application at several points in your script. Don't do that. Create the Excel instance once, use this one instance throughout your entire script, and terminate it when your script ends.
Edit: This is what causes your issue:
Set Stock = oExcel.Cells(RR,5)
Set ID = oExcel.Cells(RR,3)
...
oBook1.Close
...
oExcel.Cells(r,4).value = Stock '<<< Area of issue
oExcel.Cells(r,2).value = ID '<<<
You assign Range objects (returned by the Cells property) to the variables Stock and ID, but then close the workbook with the data these objects reference.
Since you want to transfer values anyway, assign the value of the respective cells to the variables Stock and ID:
Stock = oExcel.Cells(RR,5).Value
ID = oExcel.Cells(RR,3).Value
Also, I'd recommend to avoid using the Cells property of the application object. Instead use the respective property of the actual worksheet containing the data so it becomes more obvious what you're referring to:
Stock = oBook1.Sheets(1).Cells(RR,5).Value
ID = oBook1.Sheets(1).Cells(RR,5).Value
After you fixed that you'll most likely run into the next issue with the following lines:
oBook2.Save
oBook2.Close
You're closing oBook2 inside a loop without exiting from the loop. That should raise an error in the next iteration (when you try to assign the next values to the already closed workbook). Move the above two statements outside the loop or, better yet, move them to the Init procedure (after the Call Read_Write statement). From a handling perspective it's best to close/discard objects in the same context in which they were created (if possible). Helps avoiding attempts to use objects before they were created or after they were destroyed.
To further optimize your script you could even avoid the intermediate variables Stock and ID and transfer the values directly:
oBook2.Sheets(1).Cells(r,4).value = oBook1.Sheets(1).Cells(RR,5).Value
oBook2.Sheets(1).Cells(r,2).value = oBook1.Sheets(1).Cells(RR,5).Value
Re-using the same loop control variable (count) in nested loops is illegal:
Option Explicit
Dim bad_loop_counter
For bad_loop_counter = 1 To 2
WScript.Echo "outer", bad_loop_counter
For bad_loop_counter = 1 To 2
WScript.Echo "inner", bad_loop_counter
Next
Next
output:
cscript 32246593.vbs
... 32246593.vbs(6, 26) Microsoft VBScript compilation error: Invalid 'for' loop control variable
So your code won't even compile.
Excel VBA beginner coming back for more. I am creating a macro that does the following two things:
1) Searches through multiple worksheets in a single workbook for a specific piece of data (a name), variable A below
2) If that name appears, to copy a specific range of cells from the worksheet (variable X below) to the master file (variable B below)
Sub Pull_X_Click()
Dim A As Variant 'defines name
Dim B As Workbook 'defines destination file
Dim X As Workbook 'defines existing report file as source
Dim Destination As Range 'defines destination for data pulled from report
Dim ws As Worksheet
Dim rng As Range
A = Workbooks("B.xlsm").Worksheets("Summary").Range("A1").Value
Set B = Workbooks("B.xlsm")
Set X = Workbooks.Open("X.xlsm")
Set Destination = Workbooks("B").Worksheets("Input").Range("B2:S2")
'check if name is entered properly
If A = "" Then
MsgBox ("Your name is not visible; please start from the Reference tab.")
Worksheets("Reference").Activate
Exit Sub
End If
X.Activate
For Each ws In X.Worksheets
Set rng = ws.Range("A" & ws.Rows.Count).End(xlUp)
If InStr(1, rng, A) = 0 Then
Else
X.ActiveSheet.Range("$A$2:$DQ$11").AutoFilter Field:=1, Criteria1:=A
Range("A7:CD7").Select
Selection.Copy
Destination.Activate
Destination.PasteSpecial
End If
Next ws
Application.ScreenUpdating = False
End Sub
UPDATE: I managed to resolve the previous compile error, and it seems that the code (should?) work. However, it gets to this step:
X.Activate
...and then nothing happens. There's no run-time errors or anything, but it doesn't seem to be searching through the file (variable X) or pulling any of the data based on the presence of variable A. Any thoughts?
What I would've done is loop through the rows and evaluate the column in which the necessary data appears and then avoiding copy/paste just make the target range equal to the source range:
Sub SearchNCopy()
Dim A As String 'The String you are searching for
Dim b As String ' the string where you shall be searching
Dim wbs, wbt As Workbook ' Declare your workbooks
Dim wss As Worksheet
Dim i, lrow As Integer
Set wbt = Workbooks("B.xlsm") 'Set your workbooks
Set wbs = Workbooks.Open("X.xlsm")
A = wbt.Worksheets("Summary").Range("A1").Value
If A = "" Then
MsgBox ("Your name is not visible; please start from the Reference tab.")
Worksheets("Reference").Activate
Exit Sub
End If
For Each wss In wbs.Worksheets 'Loop through sheets
lrow = wss.Cells(wss.Rows.Count, "A").End(xlUp).Row 'Find last used row in each sheet - MAKE SURE YOUR SHEETS DONT HAVE BLANKS BETWEEN ENTIRES
For i = 1 To lrow Step 1 'Loop through the rows
b = wss.Range("A" & i).Value 'Assign the value to the variable from column a of the row
If Not InStr(1, b, A) = 0 Then 'Evaluate the value in the column a and if it contains the input string, do the following
wbt.Worksheets("Input").Range("B2:CC2") = wss.Range("A" & i & ":CD" & i) 'copies the range from one worksheet to another avoiding copy/paste (much faster)
End If
Next i
Next wss
End Sub
Can anyone tell me why the activeworksheet object MCWS is not being created by the following VB Script please? It is the code for a combobox in a mathcad worksheet. Thanks
Public Sub SizeBoxEvent_Start()
Dim objEX
Dim objMC
Dim MCWS
Dim objEXWB
Dim objEXWS
Dim intLineNo
Dim objRange
End Sub
Sub SizeBoxEvent_Exec(Inputs,Outputs)
Set objMC = CreateObject("MathCad.Application")
Set MCWS = objMC.ActiveWorkSheet
Set objEX = CreateObject("Excel.Application")
Set objEXWB = GetObject("C:\UB_Dims.xls")
Set objEXWS = objEXWB.worksheets("UB")
Dim MyList(71)
For i = 0 to 71
Mylist(i) = CStr(objEXWS.cells(i+3,1))
'MsgBox Mylist(i)
Next
SizeBox.List() = MyList
intLineNo = SizeBox.ListIndex + 3
objRange = "A" & intLineNo & ":U" & intLineNo
Dim varDimProps(21)
Dim varDimName(21)
For i = 1 to 21
varDimProps(i) = objEXWS.cells(intLineNo,i)
varDimName(i) = CStr(objEXWS.cells(1,i))
Next
MCWS.SetValue "Size", ABC
MCWS.SetValue "M", 288
MCWS.SetValue "D", 203
Outputs(0).Value = varDimProps
End Sub
Sub SizeBoxEvent_Stop()
Rem TODO: Add your code here
End Sub
I haven't used Public subs, so I don't know if your declarations will carry over to other subs. Here's something I picked from the PTC forum that works in Excel 2007 with Mathcad 15.0 (I understand that the excel add in is broken for later excel versions).
My guess is that you should define your objects in the functions that use them. Also, I don't think you can use Activeworksheet for the MathCad worksheet.
Private Function RunMCAD(InputFile As String)
Dim MC As Object
Set MC = CreateObject("Mathcad.Application")
MC.Visible = True
Set Wk = MC.Worksheets
Set WS = Wk.Open("C:\RDDA\RDDA 2014-10-16_excel.xmcd")
WS.SetValue "InputFile", InputFile
WS.Recalculate
WS.Save
WS.Close False
MC.Quit
RunMCAD = "Done"
End Function
In Visual studio 2010>New Project>Visual Basic>Windows>Windows forms Application, i have made a form (form1.vb) and a database (Local Database>"Database1.sdf") and a Table with 3 Columns ("Name","City","Age").
I like to copy this 3 fields and paste to document "test1.doc" (open this with Ms Office or Open Office Writer). I have bookmarks ("PasteName", PasteCity", "PasteAge") in specified places in test1.doc .
How to make a button to open the document "test1.doc" and copy - paste this 3 items from table to doc and preview before print it? (not for save - only print preview and close without save after printing)
I have find this code for MS Office but didn't work in Visual Studio. I like something similar. (this code is for a doc Form Fields - I have Bookmarks in my doc).
Private Sub cmdPrint_Click()
Dim appWord As Word.Application
Dim doc As Word.Document
Set appWord = GetObject(, "Word.Application")
Set appWord = New Word.Application
Set doc = appWord.Documents.Open("C:\WordForms\CustomerSlip.doc", , True)
With doc
.FormFields("fldCustomerID").Result = Me!CustomerID
.FormFields("fldCompanyName").Result = Me!CompanyName
.FormFields("fldContactName").Result = Me!ContactName
.Visible = True
.Activate
End With
Set doc = Nothing
Set appWord = Nothing
End Sub
Thanks programers people
This works for me. (button action)
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'Print customer slip for current customer.
Dim appWord As Word.Application
Dim doc As Word.Document
'Avoid error 429, when Word isn't open.
On Error Resume Next
Err.Clear()
'Set appWord object variable to running instance of Word.
appWord = GetObject(, "Word.Application")
If Err.Number <> 0 Then
'If Word isn't open, create a new instance of Word.
appWord = New Word.Application
End If
doc = appWord.Documents.Open("D:\Test.docx", , True)
doc.Visible()
doc.Activate()
With doc.Bookmarks
.Item("Name").Range.Text = Me.NameID.Text
.Item("City").Range.Text = Me.CityID.Text
End With
Dim dlg As Word.Dialog
dlg = appWord.Dialogs.Item(Word.WdWordDialog.wdDialogFilePrint)
dlg.Display()
'doc.Printout
doc = Nothing
appWord = Nothing
Exit Sub
errHandler:
MsgBox(Err.Number & ": " & Err.Description)
End Sub