I have written code in Excel VBA and am currently trying to convert it to vb.NET on VS 2017.
I want to copy a table in Excel, and paste it into a Word document and also keep a live link between them so that any changes in the Excel table will be transferred to the table pasted in the Word document. I managed this in Excel VBA, however vb.NET does not recognise DataType:=wdPasteOLEObject and also Placement:=wdInLine, saying they are not declared.
The following is a sample from my code:
excelApp = New Excel.Application
excelWB = excelApp.Workbooks.Open(SurveyFormLoc)
excelApp.Visible = True
With excelApp
.Sheets("Site Details").Select
.Range("B2:I11").Copy()
End With
wdApp = CreateObject("Word.Application")
wdApp.Visible = True
wdDoc = wdApp.Documents.Open(DesignReportLoc)
With wdDoc
.Application.Selection.Find.Text = "INSERT FROM SURVEY FORM"
.Application.Selection.Find.Execute()
.Application.Selection.ParagraphFormat.Alignment = 0
End With
wdApp.Selection.PasteSpecial(Link:=True, DataType:=wdPasteOLEObject, Placement:=wdInLine, DisplayAsIcon:=False)
Does anybody know what the vb.NET equivalent is to do this?
Replace wdPasteOLEObject with the number 0.
Replace wdInLine with the number 0 also.
PasteDataType Enumeration
Placement Enumeration
You could also define the Enumeration yourself if you want to preserve the readability:
Enum WdOLEPlacement
wdFloatOverText = 1
wdInLine = 0
End Enum
Enum WdPasteDataType
wdPasteBitmap = 4
wdPasteDeviceIndependentBitmap = 5
wdPasteEnhancedMetafile = 9
wdPasteHTML = 10
wdPasteHyperlink = 7
wdPasteMetafilePicture = 3
wdPasteOLEObject = 0
wdPasteRTF = 1
wdPasteShape = 8
wdPasteText = 2
End Enum
And in your code, reference like this:
DataType:=WdPasteDataType.wdPasteOLEObject
Placement:=WdOLEPlacement.wdInLine
If you run into undefined Enumerations again, you can just go to google and paste the thing you want to look up and include the word Enum and it will usually be the first result.
Related
For our incident management side of our database I am trying to have data from fields in my table(s) generate within the 149 Investigative Report, a Word document template provided by the state (see link here).
I made a read-only version of the document to preserve its integrity by forcing a save as by the user and loaded it with text form fields with bookmarks to reference (example: txtcaseintroduction).
I modified code I found in the internet for working with form fields and assigned it to a button on one of my forms to assist in generating the report (the Open reference is modified for security reasons):
Private Sub cmdPrint_Click()
'Export 149 Report.
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.
Set appWord = GetObject(, "Word.Application")
If Err.Number <> 0 Then
'If Word isn't open, create a new instance of Word.
Set appWord = New Word.Application
End If
Set doc = appWord.Documents.Add("Y:\ABC\2018\Case Files\2018 - Incident Forms\OPWDD 149 - Access Database Reference.docx", , True)
With doc
.FormFields("txtNIMRS").Result = Me.NIMRSID
.FormFields("txtInternalID").Result = Me.InternalIncidentID
.FormFields("txtIncidentDate").Result = Me.[IncidentOccurrenceDate]
.FormFields("txtDiscoverydate").Result = Me.[IncidentReportDate]
.FormFields("txtCaseIntroduction").Result = Me.CaseIntroduction
.FormFields("txtIncidentLocation").Result = Me.Location
.FormFields("txtBackground").Result = Me.BackgroundInfo
.FormFields("txtProtections").Result = Me.ImmedProtec
.FormFields("txtQuestion").Result = Me.InvestQuestion
.FormFields("txtTestName").Result = Me.[TestimonialEvidence]
.FormFields("txtDocumentaryE").Result = Me.[DocumentaryEvidence]
.FormFields("txtDemonstrativeE").Result = Me.[DemonstrativeEvidence]
.FormFields("txtPhysicalE").Result = Me.[PhysicalEvidence]
.FormFields("txtWSName").Result = Me.[WrittenStatements]
.FormFields("txtSummary").Result = Me.SummaryEvidence
.FormFields("txtConclusions").Result = Me.Text409
.FormFields("txtRecommendations").Result = Me.Text411
.FormFields("txtInvestigator").Result = Me.Investigator_s__Assigned
.FormFields("txtdatereport").Result = Me.Investigative_Report_Completion_Date
.Visible = True
.Activate
End With
Set doc = Nothing
Set appWord = Nothing
Exit Sub
errHandler:
MsgBox Err.Number & ": " & Err.Description
End Sub
The following fields work:
.FormFields("txtNIMRS").Result = Me.NIMRSID
.FormFields("txtInternalID").Result = Me.InternalIncidentID
.FormFields("txtIncidentDate").Result = Me.[IncidentOccurrenceDate]
.FormFields("txtDiscoverydate").Result = Me.[IncidentReportDate]
.FormFields("txtIncidentLocation").Result = Me.Location
.FormFields("txtBackground").Result = Me.BackgroundInfo
.FormFields("txtProtections").Result = Me.ImmedProtec
.FormFields("txtQuestion").Result = Me.InvestQuestion
.FormFields("txtConclusions").Result = Me.Text409
.FormFields("txtRecommendations").Result = Me.Text411
.FormFields("txtdatereport").Result = Me.Investigative_Report_Completion_Date
The remaining fields (case introduction, investigator, and the attachment fields) do not. All of these fields exist on the same table. It is also noted that case introduction used to work, but stopped working as I tried to figure out more form fields to apply to the document and reference. The goal was to have the investigator essentially do all of their work in the database and then export it to the required format for submission to the state.
My question: what do I need to do to the above code to get the non-working fields functional in populating the Word document?
Responding to questions in comments
No error that occurs; the text-boxes are simply not populating when I engage the button.
The form fields do not need to be present in the result document. They are simply "targets" for the data.
Since the form fields do not need to be retained in the result document the simplest approach would be to simply insert the data to the FormField.Range, which will replace (remove) the form field. The entire code can be written in this manner if consistency is important (how the end result looks to the user), but from a programming stand-point need not be.
Note: If Forms protection is activated, it needs to be turned off for this approach to work
If doc.ProtectionType <> -1 Then doc.Unprotect '-1 = wdNoProtection
Sample code line for a string longer than 255 characters
.FormFields("txtCaseIntroduction").Range = Me.CaseIntroduction
I am using below VBS code to export one chart (from QlikView) to excel.
Reason I am using Number format = ‘#’ and paste special because if I do not use it then values in the chart like ‘22001E-07’ gets converted to 2.20E-03
sub GPOTest1
set oXL=CreateObject("Excel.Application")
oXL.visible=True
oXL.Workbooks.Add
aSheetObj=Array("CH01")
for i=0 to UBound(aSheetObj)
oXL.Sheets.Add
Set oSH = oXL.ActiveSheet
oSH.Range("A1").Select
Set obj = ActiveDocument.GetSheetObject(aSheetObj(i))
obj.CopyTableToClipboard True
oSH.Columns("B").NumberFormat = "#" ‘In “B” column I get values like 22001E-07
oSH.PasteSpecial -4163
sCaption=obj.GetCaption.Name.v
set obj=Nothing
oSH.Rows("1:1").Select
oXL.Selection.Font.Bold = True
oSH.Cells.Select
oXL.Selection.Columns.AutoFit
oSH.Range("A1").Select
oSH.Name=left(sCaption,30)
set oSH=Nothing
next
set oXL=Nothing
end sub
After running it for the first time, from 2nd time I get message
PasteSpecial method of Worksheet class failed
Referred following link, however, issue persists:
use macro to convert number format to text in Excel
You shouldn't systematically create an Excel instance. Your code leaves Excel open. Once Excel is open, the next time around, you can get a reference to it using GetObject. See the approach taken in the code below, where I've also simplified a couple things:
Sub GPOTest1()
On Error Resume Next
Set oXL = CreateObject("Excel.Application")
If oXL Is Nothing Then
Set oXL = GetObject(Class:="Excel.Application")
End If
On Error GoTo 0
oXL.Visible = True
Set oWB = oXL.Workbooks.Add
aSheetObj = Array("CH01")
For i = 0 To UBound(aSheetObj)
Set oSH = oWB.Sheets.Add
Set obj = ActiveDocument.GetSheetObject(aSheetObj(i))
obj.CopyTableToClipboard True
oSH.Columns("B").NumberFormat = "#" 'In “B” column I get values like 22001E-07
oSH.PasteSpecial -4163
oSH.Rows("1:1").Font.Bold = True
oSH.Columns.AutoFit
oSH.Range("A1").Select
oSH.Name = Left(obj.GetCaption.Name.v, 30)
Set oSH = Nothing
Set obj = Nothing
Next
Set oXL = Nothing
End Sub
I am giving my required Excel Template here. As my present scenario this excel will be stored in a fix path. But CSV will generate everyday.
My vb script should execute everyday to collect data from csv and write into this Excel , but small customization needed.
Here First 3 rows are Fixed Header, I need to convert csv and write values in excel from 4th row. but its obvious we have old data there. so it should delete 4th row to 7th row and put csv value as per required place. With proper border also.
Now tell me is it possible to modify my vbs to get this type of output?
to run the script like below ...
MyScript.vbs : which needs two argument to execute
cscript C:\Test\MyScript.vbs \\C:\Test\Sample.CSV \\C:\Test\Sample.xlsx
Original script is below. but I want to view like below screenshot.
srccsvfile = Wscript.Arguments(0)
tgtxlsfile = Wscript.Arguments(1)
'Create Spreadsheet
'Look for an existing Excel instance.
On Error Resume Next ' Turn on the error handling flag
Set objExcel = GetObject(, "Excel.Application")
'If not found, create a new instance.
If Err.Number = 429 Then '> 0
Set objExcel = CreateObject("Excel.Application")
End If
objExcel.Visible = False
objExcel.DisplayAlerts = False
'Import CSV into Spreadsheet
Set objWorkbook = objExcel.Workbooks.Open(srccsvfile)
Set objWorksheet1 = objWorkbook.Worksheets(1)
'Adjust width of columns
Set objRange = objWorksheet1.UsedRange
objRange.EntireColumn.Autofit()
'This code could be used to AutoFit a select number of columns
'For intColumns = 1 To 17
' objExcel.Columns(intColumns).AutoFit()
'Next
'Make Headings Bold
objExcel.Rows(1).Font.Bold = True
'Freeze header row
With objExcel.ActiveWindow
.SplitColumn = 0
.SplitRow = 1
End With
objExcel.ActiveWindow.FreezePanes = True
'Add Data Filters to Heading Row
objExcel.Rows(1).AutoFilter
'set header row gray
objExcel.Rows(1).Interior.ColorIndex = 15
'-0.249977111117893
aList=Array("NOT ", "NO ", "NONE", "!")
For each item in aList
For Each c In objWorksheet1.UsedRange
If InStr(1, c.Value, item) > 0 Then
c.Interior.ColorIndex = 6
End If
Next
next
'Save Spreadsheet, 51 = Excel 2007-2010
objWorksheet1.SaveAs tgtxlsfile, 51
'Release Lock on Spreadsheet
objExcel.Quit()
Set objWorksheet1 = Nothing
Set objWorkbook = Nothing
Set objExcel = Nothing
Header and Legend should be Fixed as screenshot.
But there can be alternate way also. If I can get some modified vb script which can create Header like the above screenshot (i.e. merge cell, border, freeze, remove gridlines) and add legend at the bottom, then I don't need to write into existing excel everyday. All-time when vbs executes it should replace old excel (if exist) with this proper format.
record a macro of creating the header and legend. then edit the code for clean up all the .Select ... Selection statements. ... in your code that you posted, you can autofit all the columns with one command by using one of these
ActiveSheet.Columns("A:Q").AutoFit
ActiveSheet.Range(Columns(1), Columns(17)).AutoFit
I have been trying to find a specific data in Excel through a WinForm application and then try to fetch the next value in the same row using vb.net.
Example:
ElementName Value
Age 24
Name John Clan
Music Rock
Suppose if I want to find Age. then I want to make the code return as 24 searching it from Excel file.
I tried pulling the whole Excel data into a Dataset but it wasn't helpful.
Kindly guide me.
Imports Interop = Microsoft.Office.Interop.Excel
'Find In Excel
Private Function FindValueInExcel(ByVal sTextToFind)
Dim currentFind As Interop.Range = Nothing
Dim firstFind As Interop.Range = Nothing
Dim xlappFirstFile As Interop.Application = Nothing
Dim sSearchedValue As String
xlappFirstFile = CreateObject("Excel.Application")
xlappFirstFile.Workbooks.Open("D:\Sample.xlsx")
Dim rngSearchValue As Interop.Range = xlappFirstFile.Range("A1", "C5")
currentFind = rngSearchValue.Find(sTextToFind, , _
Interop.XlFindLookIn.xlValues, Interop.XlLookAt.xlPart, _
Interop.XlSearchOrder.xlByRows, Interop.XlSearchDirection.xlNext, False)
If Not currentFind Is Nothing Then
sSearchedValue = DirectCast(DirectCast(currentFind.EntireRow, Microsoft.Office.Interop.Excel.Range).Value2, System.Object)(1, 3).ToString()
Else
sSearchedValue = ""
End If
Return sSearchedValue
End Function
Link which helped me - http://msdn.microsoft.com/en-us/library/e4x1k99a.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1
I'm creating a ProcessBook display that populates an embedded Microsoft Office 11.0 Spreadsheet object (Office 2003) with a set of entries. I'm then calculating aggregate data about them; this aggregate data should not be visible in spreadsheet form onscreen, but does need to be used to generate a bar chart. The data is currently being used to populate a separate Microsoft Office 11.0 Spreadsheet object. It's organized such that the title of each bar chart is in column A and the corresponding value is in column B.
Since this is ProcessBook, I've had some difficulty even gaining access to embedded objects, but I've managed to embed and gain access to a ChartSpace object, as well as a child ChChart object. Unfortunately, I can't figure out how to either manually set the values of the bars or how to use the .SetData or .SetSpreadsheetData methods to point it to an object that I've populated.
Accessing the ChartSpace object is pretty straightforward: ThisDisplay.ChartSpace1
I can then add a Chart and access it fairly easily:
Dim objChart as ChChart
Set objChart = ThisDisplay.ChartSpace1.Charts.Add(0)
I can access my spreadsheet values pretty easily as well:
strBarName = ThisDisplay.sstChartData.Range("A2").Value
intBarVal = ThisDisplay.sstChartData.Range("B2").Value
How do I actually set the data source or manually set the values of the bars in the ChChart object? Alternatively, how do I use a different object to accomplish the same goal?
Apparently persistence is the key here. I managed to determine how to both add values manually and how to refer to the existing spreadsheet object. Both examples take heavily from the online ChChart documentation; I guess I was just tired when I attempted it in the first place and must have mistyped something somewhere.
Public Sub AddValuesToChartManually()
Dim objChart As ChChart
With ThisDisplay.ChartSpace1
Do While .Charts.Count > 0
ThisDisplay.ChartSpace1.Charts.Delete (0)
Loop
Set objChart = .Charts.Add
objChart.HasTitle = True
objChart.Title.Caption = "Chart Title"
objChart.Axes.Item(0).HasTitle = True
objChart.Axes.Item(1).HasTitle = True
objChart.Axes.Item(0).Title.Caption = "Axis 0"
objChart.Axes.Item(1).Title.Caption = "Axis 1"
objChart.HasLegend = False
Dim astrHeaders(0 To 4) As String
Dim aintValues1(0 To 4) As String
Dim aintValues2(0 To 4) As String
Dim astrSeries1(0) As String
Dim astrSeries2(0) As String
astrHeaders(0) = "AL1"
astrHeaders(1) = "AL2"
astrHeaders(2) = "AL3"
astrHeaders(3) = "AL4"
astrHeaders(4) = "AL5"
astrSeries(0) = "Series Name"
aintValues(0) = 1
aintValues(1) = 3
aintValues(2) = 17
aintValues(3) = 1
aintValues(4) = 7
objChart.Type = .Constants.chChartTypeColumnClustered
Call objChart.SetData(chDimSeriesName, .Constants.chDataLiteral, astrSeries)
Call objChart.SetData(chDimCategories, .Constants.chDataLiteral, astrHeaders)
Call objChart.SeriesCollection(0).SetData(.Constants.chDimValues, .Constants.chDataLiteral, aintValues)
End With
End Sub
Public Sub AddValuesFromSpreadsheet()
Dim objChart1 As ChChart
With ThisDisplay.ChartSpace1
Do While .Charts.Count > 0
ThisDisplay.ChartSpace1.Charts.Delete (0)
Loop
Set .DataSource = ThisDisplay.sstChartData
Set objChart1 = .Charts.Add
' Set the chart type.
objChart1.Type = .Constants.chChartTypeColumnClustered
' Display titles
objChart1.HasTitle = True
objChart1.Title.Caption = "Chart Title"
' Bind the series name to cell B1 in the first sheet of the spreadsheet
objChart1.SetData chDimSeriesNames, .Constants.chDataBound, "B1"
' Bind the category axis to cell A2:A28 in the first sheet of the spreadsheet.
objChart1.SetData chDimCategories, .Constants.chDataBound, "A2:A6"
' Bind the values of the data series to cells B2:B28 in the first sheet of the spreadsheet.
objChart1.SeriesCollection(0).SetData chDimValues, .Constants.chDataBound, "B2:B6"
End With
End Sub