Why is this causing a type mismatch? - sql

I have a VB6 application that calls a Crystal Report XI Report. However when I try to change the connection info I get a type mismatch. Any help would be appreciated.
Dim Report As craxddrt.Report ' This is how Report is defined
ChangeReportTblLocation Report ' This is the function where the mismatch occurs
This is the definition of ChangeReportTblLocation:
Private Function ChangeReportTblLocation(ByRef pReport As craxddrt.Report) As Boolean
Dim ConnectionInfo As craxddrt.ConnectionProperties
Dim crxTables As craxddrt.DatabaseTables
Dim crxTable As craxddrt.DatabaseTable
Dim crxSections As craxddrt.Sections
Dim crxSection As craxddrt.section
Dim crxSubreportObj As craxddrt.SubreportObject
Dim crxReportObjects As craxddrt.ReportObjects
Dim crxSubreport As craxddrt.Report
Dim ReportObject As Object
Dim Y As Integer
Dim lsDatabase As String
On Error GoTo errHandle_CRTL
lsDatabase = GetCurrentUserRoot("SOFTWARE\COTTSYSTEMS\APP", "Database")
If lsDatabase = "" Then
lsDatabase = gConn.DefaultDatabase
End If
If lsDatabase = "" Then
lsDatabase = "frasys"
End If
With pReport
For Y = 1 To .Database.Tables.Count
Set ConnectionInfo = .Database.Tables(Y).ConnectionProperties
ConnectionInfo.DeleteAll
ConnectionInfo.Add "DSN", frasysdsn
ConnectionInfo.Add "Database", lsDatabase
'This is the Line that causes the type mismatch
.Database.Tables(Y).Location = lsDatabase & ".dbo." & Database.Tables(Y).Location
Next Y
Set crxSections = .Sections
For Each crxSection In crxSections
Set crxReportObjects = crxSection.ReportObjects
For Each ReportObject In crxReportObjects
If ReportObject.Kind = crSubreportObject Then
Set crxSubreportObj = ReportObject
Set crxSubreport = crxSubreportObj.OpenSubreport
Set crxTables = crxSubreport.Database.Tables
For Y = 1 To crxTables.Count
Set crxTable = crxTables.Item(Y)
crxTable.Location = lsDatabase & ".dbo." & crxTable.Location
Next Y
End If
Next ReportObject
Next crxSection
End With
Set ConnectionInfo = Nothing
Set crxTables = Nothing
Set crxTable = Nothing
Set crxSections = Nothing
Set crxSection = Nothing
Set crxSubreportObj = Nothing
Set crxReportObjects = Nothing
Set crxSubreport = Nothing
Set ReportObject = Nothing
ChangeReportTblLocation = True
Exit Function
errHandle_CRTL:
Screen.MousePointer = vbDefault
MsgBox err.Number, err.Description, "ChangeReportTblLocation", err.Source
End Function

I think its just a typo:
.Database.Tables(Y).Location = lsDatabase & ".dbo." & .Database.Tables(Y).Location
I've added a . before the second Database.Tables(Y).Location in this line.
This does suggest though that you aren't using Option Explicit in your code. I can't stress strongly enough how important it is to use this. It will save you lots of time looking for odd typos (like this) and save your code from doing all sorts of weird things.

try using
call ChangeReportTblLocation(Report)

Related

XmlDocument in Outlook VBA

I am trying to adapt this answer, which I believe is in VB.NET, for use with Outlook VBA.
I made some progress by getting the syntax corrected for VBA, but I do not know how to resolve "Compile error: User-defined type not defined" on the line
Dim CurrentXML As XmlDocument
Tool > References includes Microsoft XML, v6.0 but searching for XmlDocument in Object Browser returns no results.
The complete code is as follows:
Sub Search2()
' https://stackoverflow.com/a/50145011/18573
Dim sFilter As String
Dim CurrentExplorer As Outlook.Explorer
Set CurrentExplorer = Nothing
Dim CurrentView As Outlook.View
Set CurrentView = Nothing
' ERROR ON THE FOLLOWING LINE
Dim CurrentXML As XmlDocument
Set CurrentXML = New XmlDocument
Dim CurrentFilterNodes, CurrentViewNodes As XmlNodeList
Dim CurrentFilterNode, CurrentParentNode As XmlNode
sFilter = "urn:schemas:httpmail:subject LIKE '%Build Error%'"
CurrentExplorer = TryCast(ExplorerObj, Outlook.Explorer)
If (CurrentExplorer Is Not Nothing) Then
CurrentView = CurrentExplorer.CurrentView
If (CurrentView Is Not Nothing) Then
CurrentXML.LoadXML (CurrentView.xml)
CurrentFilterNodes = _
CurrentXML.getElementsByTagName("filter")
If CurrentFilterNodes.Count > 0 Then
For y = 0 To CurrentFilterNodes.Count - 1
CurrentFilterNode = CurrentFilterNodes(y)
If CurrentFilterNode.HasChildNodes Then
For i = CurrentFilterNode.ChildNodes.Count - 1 To 0 Step -1
CurrentFilterNode.RemoveChild (CurrentFilterNode.ChildNodes(i))
Next i
End If
Next y
CurrentFilterNode = CurrentFilterNodes(0)
CurrentFilterNode.appendChild ( _
CurrentXML.createTextNode(sFilter))
Else
CurrentViewNodes = CurrentXML.getElementsByTagName("view")
If CurrentViewNodes Is Not Nothing Then
CurrentParentNode = CurrentViewNodes(0)
CurrentFilterNode = CurrentXML.createElement("filter")
CurrentParentNode.appendChild (CurrentFilterNode)
CurrentFilterNode.appendChild (CurrentXML.createTextNode(sFilter))
End If
End If
CurrentView.xml = CurrentXML.InnerXml
CurrentView.Apply
Marshal.ReleaseComObject (CurrentView)
End If
End Sub
The VBA code for Outlook should look like as follows
Option Explicit
Sub Search2()
' https://stackoverflow.com/a/50145011/18573
' Add reference Microsoft XML, v6.0
Dim sFilter As String
Dim oExplorer As Explorer
Dim oView As View
Dim oXML As DOMDocument60
Dim cFilterNodes As IXMLDOMNodeList
Dim cViewNodes As IXMLDOMNodeList
Dim oFilterNode As IXMLDOMNode
Dim oParentNode As IXMLDOMNode
Dim y As Long
Dim i As Long
sFilter = "urn:schemas:httpmail:subject LIKE '%Build Error%'"
Set oXML = New DOMDocument60
Set oExplorer = ActiveExplorer
If Not oExplorer Is Nothing Then
Set oView = oExplorer.CurrentView
If Not oView Is Nothing Then
oXML.LoadXML oView.XML
Set cFilterNodes = oXML.getElementsByTagName("filter")
If cFilterNodes.Length > 0 Then
For y = 0 To cFilterNodes.Length - 1
Set oFilterNode = cFilterNodes(y)
If oFilterNode.HasChildNodes Then
For i = oFilterNode.ChildNodes.Length - 1 To 0 Step -1
oFilterNode.RemoveChild oFilterNode.ChildNodes(i)
Next
End If
Next
Set oFilterNode = cFilterNodes(0)
oFilterNode.appendChild oXML.createTextNode(sFilter)
Else
Set cViewNodes = oXML.getElementsByTagName("view")
If cViewNodes.Length > 0 Then
Set oParentNode = cViewNodes(0)
Set oFilterNode = oXML.createElement("filter")
oParentNode.appendChild oFilterNode
oFilterNode.appendChild oXML.createTextNode(sFilter)
End If
End If
Else
Set cViewNodes = oXML.getElementsByTagName("view")
If cViewNodes.Length > 0 Then
Set oParentNode = cViewNodes(0)
Set oFilterNode = oXML.createElement("filter")
oParentNode.appendChild oFilterNode
oFilterNode.appendChild oXML.createTextNode(sFilter)
End If
End If
oView.XML = oXML.XML
oView.Apply
End If
End Sub

Getting Error "ActiveX component can't create object while connecting with CMS supervisor

Hi This is the exact function i am using while pulling the report from CMS R17. Error line is quoted in * Set cvsConn = New cvsConnection * stars.
Function CMSConn(sUserID As String, sPassword As String, sServerIP As String)
Dim cvsApp As cvsApplication
Dim cvsSrv As cvsServer
Dim cvsConn As cvsConnection
Dim iServer As Integer
Dim bConnected As Boolean
bConnected = False
Set cvsApp = New cvsApplication
Set cvsSrv = New cvsServer
***Set cvsConn = New cvsConnection***
'Checks to see if already connected to server
For iServer = 1 To cvsApp.Servers.Count
Set cvsSrv = cvsApp.Servers(iServer)
If cvsSrv.ServerKey Like "*\" & sServerIP & "\*\*\*" Then
bConnected = True
'MsgBox "Avaya Connected! Click OK to proceed."
Exit For
End If
Next iServer
'Initiates connection if one not already established
If bConnected = False Then
If cvsApp.CreateServer(sUserID, sPassword, "", sServerIP, False, "ENU",
cvsSrv, cvsConn) Then
If cvsConn.Login(sUserID, sPassword, sServerIP, "ENU") Then
End If
End If
End If
'Executes CMS report
Dim cvsRepInfo As Object
Dim cvsRepProp As Object
Dim cvsLog As Object
Dim b As Boolean
On Error Resume Next
cvsSrv.Reports.ACD = 1
Set cvsRepInfo = cvsSrv.Reports.Reports("Historical\Designer\Skill Interval SvcLvl")
If cvsRepInfo Is Nothing Then
If cvsSrv.Interactive Then
MsgBox "The report was not found on ACD.", vbCritical Or vbOKOnly,
"Avaya CMS Supervisor"
Else
Set cvsLog = CreateObject("ACSERR.cvsLog")
cvsLog.AutoLogWrite "The report was not found on ACD."
Set cvsLog = Nothing
End If
Else
b = cvsSrv.Reports.CreateReport(cvsRepInfo, cvsRepProp)
If b Then
Application.DisplayAlerts = False
cvsRepProp.Window.Top = 40
cvsRepProp.Window.Left = 40
cvsRepProp.Window.Width = 40
cvsRepProp.Window.Height = 40
cvsRepProp.SetProperty "Splits/Skills",
ThisWorkbook.Sheets("DAILY").Range("x7").Value
cvsRepProp.SetProperty "Date",
ThisWorkbook.Sheets("DAILY").Range("x8").Value
cvsRepProp.SetProperty "Times",
ThisWorkbook.Sheets("DAILY").Range("x9").Value
b = cvsRepProp.ExportData("", 9, 0, False, True, True)
'Closes report
If bConnected = True Then
cvsRepProp.Quit
Else
If Not cvsSrv.Interactive Then cvsSrv.ActiveTasks.Remove
cvsRepProp.TaskID
End If
Set cvsRepProp = Nothing
End If
End If
'Terminates server instance and connection
Set cvsRepInfo = Nothing
If Not cvsSrv.Interactive Then cvsApp.Servers.Remove cvsSrv.ServerKey
If bConnected = False Then
cvsConn.Logout
cvsConn.Disconnect
cvsSrv.Connected = False
End If
Set cvsConn = Nothing
Set cvsSrv = Nothing
Set cvsApp = Nothing
End Function
End Sub

Parsing xml string in VBA

I am trying to parse xml document that i am getting from a website.
from some reason i cant figure out i cant parse the value inside the 'RATE' node.
the xml string seems O.K.
but in the end of the code (commented) i get Object variable or With block variable not set error.
i will be grateful for any help.
XML STRING:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<CURRENCIES>
<LAST_UPDATE>2016-01-25</LAST_UPDATE>
<CURRENCY>
<NAME>Dollar</NAME>
<UNIT>1</UNIT>
<CURRENCYCODE>USD</CURRENCYCODE>
<COUNTRY>USA</COUNTRY>
<RATE>3.982</RATE>
<CHANGE>0.277</CHANGE>
</CURRENCY>
</CURRENCIES>
VBA CODE:
Private Sub loadXMLString(xmlString)
Dim strXML As String
Dim xNode As IXMLDOMNode
Dim XDoc As MSXML2.DOMDocument
strXML = xmlString
Set XDoc = New MSXML2.DOMDocument
If Not XDoc.LoadXML(strXML) Then 'strXML is the string with XML'
Err.Raise XDoc.parseError.ErrorCode, , XDoc.parseError.reason
End If
Set xNode = XDoc.FirstChild
Debug.Print xNode.SelectSingleNode("RATE").Text ' here i get the Object variable or With block variable not set error
Debug.Print xNode.ChildNodes(2).SelectSingleNode("RATE").Text ' also with that try i get the Object variable or With block variable not set error
End Sub
UPDATE:
i found the problem (as i wrote down in the comments to #Nathan).
the problem is the <?xml version="1.0" encoding="utf-8" standalone="yes"?> node
Tested it an this code is working:
so how can i do that with out to remove this node as a substring, there must be a way i guess, but i dont have a lot of experience working with XML
Private Sub loadXMLString(xmlString)
Dim strXML As String
Dim xNode As IXMLDOMNode
Dim XDoc As MSXML2.DOMDocument
strXML = "<CURRENCIES>" & _
"<LAST_UPDATE>2016-01-25</LAST_UPDATE>" & _
"<CURRENCY>" & _
"<NAME>Dollar</NAME>" & _
"<UNIT>1</UNIT>" & _
"<CURRENCYCODE>USD</CURRENCYCODE>" & _
"<COUNTRY>USA</COUNTRY>" & _
"<RATE>3.982</RATE>" & _
"<CHANGE>0.277</CHANGE>" & _
"</CURRENCY>" & _
"</CURRENCIES>"
Set XDoc = New MSXML2.DOMDocument
If Not XDoc.LoadXML(strXML) Then 'strXML is the string with XML'
Err.Raise XDoc.parseError.ErrorCode, , XDoc.parseError.reason
End If
Set xNode = XDoc.FirstChild
Debug.Print strXML
Debug.Print xNode.ChildNodes(1).SelectSingleNode("RATE").Text ' also with that try i get the Object variable or With block variable not set error
End Sub
SelectSingleNode() expects an XPath expression. Try this one:
xNode.SelectSingleNode("//RATE").Text
But in general it's not very smart to access properties of an object reference that could be Nothing – like it is in the above case, if SelectSingleNode does not find any matching node, this line will trigger a run-time error ("Object variable or With block variable not set", which effectively is a null pointer exception.)
Always guard your property accesses by validating your object reference:
Set rate = xNode.SelectSingleNode("//RATE")
If rate Is Nothing Then
Debug.Print "Error: no RATE found in document"
Else
Debug.Print rate.Text
End If
FWIW, here is a complete version of the code I would use, featuring a few nice details like a custom type for currency information and the use the Sleep() function to wait for the server to return the XML document:
Option Explicit
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Public Type CurrencyInfo
Success As Boolean
LastUpdate As Date
Name As String
Unit As Double
CurrencyCode As String
Country As String
Rate As Double
Change As Double
End Type
Private Function GetXmlDoc(url As String) As MSXML2.DOMDocument60
With New MSXML2.XMLHTTP60
.Open "GET", url, False
.send
While .readyState <> 4: Sleep 50: Wend
If .Status = 200 Then
If .responseXML.parseError.ErrorCode = 0 Then
Set GetXmlDoc = .responseXML
Else
Err.Raise vbObjectError + 1, "GetXmlDoc", "XML parser error: " & .responseXML.parseError.reason
End If
Else
Err.Raise vbObjectError + 2, "GetXmlDoc", "Server responded with status code " & .Status
End If
End With
End Function
Public Function GetCurrencyInfo(currencyName As String) As CurrencyInfo
Dim curr As MSXML2.DOMDocument60
Set curr = GetXmlDoc("http://the/url/you/use?currency=" + currencyName)
GetCurrencyInfo.Success = True
GetCurrencyInfo.LastUpdate = CDate(GetText(curr, "//LAST_UPDATE"))
GetCurrencyInfo.Name = GetText(curr, "//NAME")
GetCurrencyInfo.Unit = Val(GetText(curr, "//UNIT"))
GetCurrencyInfo.CurrencyCode = GetText(curr, "//CURRENCYCODE")
GetCurrencyInfo.Country = GetText(curr, "//COUNTRY")
GetCurrencyInfo.Rate = Val(GetText(curr, "//RATE"))
GetCurrencyInfo.Change = Val(GetText(curr, "//CHANGE"))
End Function
Private Function GetText(context As IXMLDOMNode, path As String) As String
Dim result As IXMLDOMNode
If Not context Is Nothing Then
Set result = context.SelectSingleNode(path)
If Not result Is Nothing Then GetText = result.Text
End If
End Function
Usage is as follows:
Sub Test()
Dim USD As CurrencyInfo
USD = GetCurrencyInfo("USD")
Debug.Print "LastUpdate: " & USD.LastUpdate
Debug.Print "Name: " & USD.Name
Debug.Print "Unit: " & USD.Unit
Debug.Print "CurrencyCode: " & USD.CurrencyCode
Debug.Print "Country: " & USD.Country
Debug.Print "Rate: " & USD.Rate
Debug.Print "Change: " & USD.Change
End Sub
Tried this, and got somwhere.
Dim strXML As String
Dim xNode As IXMLDOMNode
Dim XDoc As MSXML2.DOMDocument
Dim xParent As IXMLDOMNode
Dim xChild As MSXML2.IXMLDOMNode
strXML = xmlString
Set XDoc = New MSXML2.DOMDocument
If Not XDoc.Load(strXML) Then 'strXML is the string with XML'
Err.Raise XDoc.parseError.ErrorCode, , XDoc.parseError.reason
End If
Set xNode = XDoc.DocumentElement
Set xParent = xNode.FirstChild
For Each xParent In xNode.ChildNodes
For Each xChild In xParent.ChildNodes
Debug.Print xChild.Text
Next xChild
Next xParent

Finding Missing numbers in a given range

So i have a problem with my codings and was wondering if anyone can help me.
Basically i'm using VB.NET and MSSQL to make a program on finding missing numbers in between a given range set by the user. The program will read from the table and give the output on a textbox. And the above codes are so far what i can come up with. But the problem is, i get wrong output and not what i want. Here's an image of the output.
Function FindingMissingNumber() As String
Dim intX As Integer = Nothing
Dim intY As Integer = Nothing
Dim strSting As String = Nothing
Dim strSqlQUery As String = Nothing
Dim cmdSqlCommand As Data.SqlClient.SqlCommand = Nothing
Dim rdrDataReader As Data.SqlClient.SqlDataReader = Nothing
'------------------------------------------------------------------------------------------------------------------------
'-> Process
'------------------------------------------------------------------------------------------------------------------------
strSqlQUery = "Select ExReportPolicyNo From DBReport Order by ExReportPolicyNo"
Dim msSqlConnection As New Data.SqlClient.SqlConnection()
'NOTE - You may need to CHECK your connection string!!! in the line below
msSqlConnection.ConnectionString = "Data Source=SISBSQL\SISBSQL;Initial Catalog=ExceptionReport;User ID=sa;Password=123;"
cmdSqlCommand = New Data.SqlClient.SqlCommand(strSqlQUery, msSqlConnection)
If cmdSqlCommand.Connection.State = Data.ConnectionState.Closed Then cmdSqlCommand.Connection.Open()
rdrDataReader = cmdSqlCommand.ExecuteReader()
If rdrDataReader.HasRows Then
Do While rdrDataReader.Read()
intX = txtRangeLeft.Text
intY = txtRangeRight.Text
'intY = rdrDataReader.GetValue(rdrDataReader.GetOrdinal("ExReportPolicyNo"))
Do While intX <> intY
intX = intX + 1
If intX <> intY Then
strSting = strSting & intX & ", " 'if it is not, then record the non sequential number into the string
Else
Exit Do
End If
Loop
Loop
End If
If cmdSqlCommand.Connection.State = Data.ConnectionState.Open Then cmdSqlCommand.Connection.Close()
'return string
Return strSting
'tidy up
intX = Nothing
intY = Nothing
strSting = Nothing
strSqlQUery = Nothing
cmdSqlCommand = Nothing
rdrDataReader = Nothing
End Function
As you can see the program loops it multiple times, and give out the wrong output. The output should read only "286118, 286120, 286121". Question is where did i went wrong?
Try this (using linq)
Change query to return rows between start and end value
Select distinct ExReportPolicyNo From DBReport
Where ExReportPolicyNo between #start and #end
Order by ExReportPolicyNo
Create List from your query:
Dim originalList as List(Of Integer)
If rdrDataReader.HasRows Then
Do While rdrDataReader.Read()
originalList.Add(rdrDataReader.GetInt(0))
Loop
End If
Create List of range from your start and end number
//Dim rangeList = Enumerable.Range(286117, 286121 - 286117 + 1).ToList()
Dim starti = Int32.Parse(txtRangeLeft.Text)
Dim endi = Int32.Parse(txtRangeRight.Text)
Dim rangeList = Enumerable.Range(starti, endi - starti + 1).ToList()
Find all missing numbers
Dim missingList = originalList.Except(rangelist)
Create CSV string from list above
strString = String.Join(",", missingList.Select(x => x.ToString()).ToArray())

How to export datagridview to excel using vb.net?

I have a datagridview in vb.net that is filled up from the database. I've researched and I found out that there is no built in support to print directly from datagridview. I don't want to use crystal report because I'm not familiar with it.
I'm planning to export it to excel to enable me to generate report from the datagridview.
Can you provide me ways to do this?
Code below creates Excel File and saves it in D: drive
It uses Microsoft office 2007
FIRST ADD REFERRANCE (Microsoft office 12.0 object library ) to your project
Then Add code given bellow to the Export button click event-
Private Sub Export_Button_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles VIEW_Button.Click
Dim xlApp As Microsoft.Office.Interop.Excel.Application
Dim xlWorkBook As Microsoft.Office.Interop.Excel.Workbook
Dim xlWorkSheet As Microsoft.Office.Interop.Excel.Worksheet
Dim misValue As Object = System.Reflection.Missing.Value
Dim i As Integer
Dim j As Integer
xlApp = New Microsoft.Office.Interop.Excel.ApplicationClass
xlWorkBook = xlApp.Workbooks.Add(misValue)
xlWorkSheet = xlWorkBook.Sheets("sheet1")
For i = 0 To DataGridView1.RowCount - 2
For j = 0 To DataGridView1.ColumnCount - 1
For k As Integer = 1 To DataGridView1.Columns.Count
xlWorkSheet.Cells(1, k) = DataGridView1.Columns(k - 1).HeaderText
xlWorkSheet.Cells(i + 2, j + 1) = DataGridView1(j, i).Value.ToString()
Next
Next
Next
xlWorkSheet.SaveAs("D:\vbexcel.xlsx")
xlWorkBook.Close()
xlApp.Quit()
releaseObject(xlApp)
releaseObject(xlWorkBook)
releaseObject(xlWorkSheet)
MsgBox("You can find the file D:\vbexcel.xlsx")
End Sub
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
Excel Method
This method is different than many you will see. Others use a loop to write each cell and write the cells with text data type.
This method creates an object array from a DataTable or DataGridView and then writes the array to Excel. This means I can write to Excel without a loop and retain data types.
I extracted this from my library and I think I changed it enough to work with this code only, but more minor tweaking might be necessary. If you get errors just let me know and I'll correct them for you. Normally, I create an instance of my class and call these methods. If you would like to use my library then use this link to download it and if you need help just let me know.
https://zomp.co/Files.aspx?ID=zExcel
After copying the code to your solution you will use it like this.
In your button code add this and change the names to your controls.
WriteDataGrid("Sheet1", grid)
To open your file after exporting use this line
System.Diagnostics.Process.Start("The location and filename of your file")
In the WriteArray method you'll want to change the line that saves the workbook to where you want to save it. Probably makes sense to add this as a parameter.
wb.SaveAs("C:\MyWorkbook.xlsx")
Public Function WriteArray(Sheet As String, ByRef ObjectArray As Object(,)) As String
Try
Dim xl As Excel.Application = New Excel.Application
Dim wb As Excel.Workbook = xl.Workbooks.Add()
Dim ws As Excel.Worksheet = wb.Worksheets.Add()
ws.Name = Sheet
Dim range As Excel.Range = ws.Range("A1").Resize(ObjectArray.GetLength(0), ObjectArray.GetLength(1))
range.Value = ObjectArray
range = ws.Range("A1").Resize(1, ObjectArray.GetLength(1) - 1)
range.Interior.Color = RGB(0, 70, 132) 'Con-way Blue
range.Font.Color = RGB(Drawing.Color.White.R, Drawing.Color.White.G, Drawing.Color.White.B)
range.Font.Bold = True
range.WrapText = True
range.HorizontalAlignment = Excel.XlHAlign.xlHAlignCenter
range.VerticalAlignment = Excel.XlVAlign.xlVAlignCenter
range.Application.ActiveWindow.SplitColumn = 0
range.Application.ActiveWindow.SplitRow = 1
range.Application.ActiveWindow.FreezePanes = True
wb.SaveAs("C:\MyWorkbook.xlsx")
wb.CLose()
xl.Quit()
xl = Nothing
wb = Nothing
ws = Nothing
range = Nothing
ReleaseComObject(xl)
ReleaseComObject(wb)
ReleaseComObject(ws)
ReleaseComObject(range)
Return ""
Catch ex As Exception
Return "WriteArray()" & Environment.NewLine & Environment.NewLine & ex.Message
End Try
End Function
Public Function WriteDataGrid(SheetName As String, ByRef dt As DataGridView) As String
Try
Dim l(dt.Rows.Count + 1, dt.Columns.Count) As Object
For c As Integer = 0 To dt.Columns.Count - 1
l(0, c) = dt.Columns(c).HeaderText
Next
For r As Integer = 1 To dt.Rows.Count
For c As Integer = 0 To dt.Columns.Count - 1
l(r, c) = dt.Rows(r - 1).Cells(c)
Next
Next
Dim errors As String = WriteArray(SheetName, l)
If errors <> "" Then
Return errors
End If
Return ""
Catch ex As Exception
Return "WriteDataGrid()" & Environment.NewLine & Environment.NewLine & ex.Message
End Try
End Function
Public Function WriteDataTable(SheetName As String, ByRef dt As DataTable) As String
Try
Dim l(dt.Rows.Count + 1, dt.Columns.Count) As Object
For c As Integer = 0 To dt.Columns.Count - 1
l(0, c) = dt.Columns(c).ColumnName
Next
For r As Integer = 1 To dt.Rows.Count
For c As Integer = 0 To dt.Columns.Count - 1
l(r, c) = dt.Rows(r - 1).Item(c)
Next
Next
Dim errors As String = WriteArray(SheetName, l)
If errors <> "" Then
Return errors
End If
Return ""
Catch ex As Exception
Return "WriteDataTable()" & Environment.NewLine & Environment.NewLine & ex.Message
End Try
End Function
I actually don't use this method in my Database program because it's a slow method when you have a lot of rows/columns. I instead create a CSV from the DataGridView. Writing to Excel with Excel Automation is only useful if you need to format the data and cells otherwise you should use CSV. You can use the code after the image for CSV export.
CSV Method
Private Sub DataGridToCSV(ByRef dt As DataGridView, Qualifier As String)
Dim TempDirectory As String = "A temp Directory"
System.IO.Directory.CreateDirectory(TempDirectory)
Dim oWrite As System.IO.StreamWriter
Dim file As String = System.IO.Path.GetRandomFileName & ".csv"
oWrite = IO.File.CreateText(TempDirectory & "\" & file)
Dim CSV As StringBuilder = New StringBuilder()
Dim i As Integer = 1
Dim CSVHeader As StringBuilder = New StringBuilder()
For Each c As DataGridViewColumn In dt.Columns
If i = 1 Then
CSVHeader.Append(Qualifier & c.HeaderText.ToString() & Qualifier)
Else
CSVHeader.Append("," & Qualifier & c.HeaderText.ToString() & Qualifier)
End If
i += 1
Next
'CSV.AppendLine(CSVHeader.ToString())
oWrite.WriteLine(CSVHeader.ToString())
oWrite.Flush()
For r As Integer = 0 To dt.Rows.Count - 1
Dim CSVLine As StringBuilder = New StringBuilder()
Dim s As String = ""
For c As Integer = 0 To dt.Columns.Count - 1
If c = 0 Then
'CSVLine.Append(Qualifier & gridResults.Rows(r).Cells(c).Value.ToString() & Qualifier)
s = s & Qualifier & gridResults.Rows(r).Cells(c).Value.ToString() & Qualifier
Else
'CSVLine.Append("," & Qualifier & gridResults.Rows(r).Cells(c).Value.ToString() & Qualifier)
s = s & "," & Qualifier & gridResults.Rows(r).Cells(c).Value.ToString() & Qualifier
End If
Next
oWrite.WriteLine(s)
oWrite.Flush()
'CSV.AppendLine(CSVLine.ToString())
'CSVLine.Clear()
Next
'oWrite.Write(CSV.ToString())
oWrite.Close()
oWrite = Nothing
System.Diagnostics.Process.Start(TempDirectory & "\" & file)
GC.Collect()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
DATAGRIDVIEW_TO_EXCEL((DataGridView1)) ' PARAMETER: YOUR DATAGRIDVIEW
End Sub
Private Sub DATAGRIDVIEW_TO_EXCEL(ByVal DGV As DataGridView)
Try
Dim DTB = New DataTable, RWS As Integer, CLS As Integer
For CLS = 0 To DGV.ColumnCount - 1 ' COLUMNS OF DTB
DTB.Columns.Add(DGV.Columns(CLS).Name.ToString)
Next
Dim DRW As DataRow
For RWS = 0 To DGV.Rows.Count - 1 ' FILL DTB WITH DATAGRIDVIEW
DRW = DTB.NewRow
For CLS = 0 To DGV.ColumnCount - 1
Try
DRW(DTB.Columns(CLS).ColumnName.ToString) = DGV.Rows(RWS).Cells(CLS).Value.ToString
Catch ex As Exception
End Try
Next
DTB.Rows.Add(DRW)
Next
DTB.AcceptChanges()
Dim DST As New DataSet
DST.Tables.Add(DTB)
Dim FLE As String = "" ' PATH AND FILE NAME WHERE THE XML WIL BE CREATED (EXEMPLE: C:\REPS\XML.xml)
DTB.WriteXml(FLE)
Dim EXL As String = "" ' PATH OF/ EXCEL.EXE IN YOUR MICROSOFT OFFICE
Shell(Chr(34) & EXL & Chr(34) & " " & Chr(34) & FLE & Chr(34), vbNormalFocus) ' OPEN XML WITH EXCEL
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Regarding your need to 'print directly from datagridview', check out this article on CodeProject:
The DataGridViewPrinter Class
There are a number of similar articles but I've had luck with the one I linked.
The following code works fine for me :)
Protected Sub ExportToExcel(sender As Object, e As EventArgs) Handles ExportExcel.Click
Try
Response.Clear()
Response.Buffer = True
Response.AddHeader("content-disposition", "attachment;filename=ExportEthias.xls")
Response.Charset = ""
Response.ContentType = "application/vnd.ms-excel"
Using sw As New StringWriter()
Dim hw As New HtmlTextWriter(sw)
GvActifs.RenderControl(hw)
'Le format de base est le texte pour éviter les problèmes d'arrondis des nombres
Dim style As String = "<style> .textmode { } </style>"
Response.Write(Style)
Response.Output.Write(sw.ToString())
Response.Flush()
Response.End()
End Using
Catch ex As Exception
lblMessage.Text = "Erreur export Excel : " & ex.Message
End Try
End Sub
Public Overrides Sub VerifyRenderingInServerForm(control As Control)
' Verifies that the control is rendered
End Sub
Hopes this help you.
Dim rowNo1 As Short
Dim numrow As Short
Dim colNo1 As Short
Dim colNo2 As Short
rowNo1 = 1
colNo1 = 1
colNo2 = 1
numrow = 1
ObjEXCEL = CType(CreateObject("Excel.Application"), Microsoft.Office.Interop.Excel.Application)
objEXCELBook = CType(ObjEXCEL.Workbooks.Add, Microsoft.Office.Interop.Excel.Workbook)
objEXCELSheet = CType(objEXCELBook.Worksheets(1), Microsoft.Office.Interop.Excel.Worksheet)
ObjEXCEL.Visible = True
For numCounter = 0 To grdName.Columns.Count - 1
' MsgBox(grdName.Columns(numCounter).HeaderText())
If grdName.Columns(numCounter).Width > 0 Then
ObjEXCEL.Cells(1, numCounter + 1) = grdName.Columns(numCounter).HeaderText()
End If
' ObjEXCEL.Cells(1, numCounter + 1) = grdName.Columns.GetFirstColumn(DataGridViewElementStates.Displayed)
Next numCounter
ObjEXCEL.Range("A:A").ColumnWidth = 10
ObjEXCEL.Range("B:B").ColumnWidth = 25
ObjEXCEL.Range("C:C").ColumnWidth = 20
ObjEXCEL.Range("D:D").ColumnWidth = 20
ObjEXCEL.Range("E:E").ColumnWidth = 20
ObjEXCEL.Range("F:F").ColumnWidth = 25
For rowNo1 = 0 To grdName.RowCount - 1
For colNo1 = 0 To grdName.ColumnCount - 1
If grdName.Columns(colNo1).Width > 0 Then
If Trim(grdName.Item(colNo1, rowNo1).Value) <> "" Then
'If IsDate(grdName.Item(colNo1, rowNo1).Value) = True Then
' ObjEXCEL.Cells(numrow + 1, colNo2) = Format(CDate(grdName.Item(colNo1, rowNo1).Value), "dd/MMM/yyyy")
'Else
ObjEXCEL.Cells(numrow + 1, colNo2) = grdName.Item(colNo1, rowNo1).Value
'End If
End If
If colNo2 >= grdName.ColumnCount Then
colNo2 = 1
Else
colNo2 = colNo2 + 1
End If
End If
Next colNo1
numrow = numrow + 1
Next rowNo1
In design mode: Set DataGridView1 ClipboardCopyMode properties to EnableAlwaysIncludeHeaderText
or on the program code
DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText
In the run time select all cells content (Ctrl+A) and copy (Ctrl+C) and paste to the Excel Program.
Let the Excel do the rest
Sorry for the inconvenient, I have been searching the method to print data directly from the datagridvew (create report from vb.net VB2012) and have not found the satisfaction result.
Above code just my though, wondering if my applications user can rely on above simple step it will be nice and I could go ahead to next step on my program progress.
A simple way of generating a printable report from a Datagridview is to place the datagridview on a Panel object. It is possible to draw a bitmap of the panel.
Here's how I do it.
'create the bitmap with the dimentions of the Panel
Dim bmp As New Bitmap(Panel1.Width, Panel1.Height)
'draw the Panel to the bitmap "bmp"
Panel1.DrawToBitmap(bmp, Panel1.ClientRectangle)
I create a multi page tiff by "breaking my datagridview items into pages.
this is how i detect the start of a new page:
'i add the rows to my datagrid one at a time and then check if the scrollbar is active.
'if the scrollbar is active i save the row to a variable and then i remove it from the
'datagridview and roll back my counter integer by one(thus the next run will include this
'row.
Private Function VScrollBarVisible() As Boolean
Dim ctrl As New Control
For Each ctrl In DataGridView_Results.Controls
If ctrl.GetType() Is GetType(VScrollBar) Then
If ctrl.Visible = True Then
Return True
Else
Return False
End If
End If
Next
Return Nothing
End Function
I hope this helps
another easy way and more flexible , after loading data into Datagrid
Private Sub Button_Export_Click(sender As Object, e As EventArgs) Handles Button_Export.Click
Dim file As System.IO.StreamWriter
file = My.Computer.FileSystem.OpenTextFileWriter("c:\1\Myfile.csv", True)
If DataGridView1.Rows.Count = 0 Then GoTo loopend
' collect the header's names
Dim Headerline As String
For k = 0 To DataGridView1.Columns.Count - 1
If k = DataGridView1.Columns.Count - 1 Then ' last column dont put , separate
Headerline = Headerline & DataGridView1.Columns(k).HeaderText
Else
Headerline = Headerline & DataGridView1.Columns(k).HeaderText & ","
End If
Next
file.WriteLine(Headerline) ' this will write header names at the first line
' collect the data
For i = 0 To DataGridView1.Rows.Count - 1
Dim DataRow As String
For k = 0 To DataGridView1.Columns.Count - 1
If k = DataGridView1.Columns.Count - 1 Then
DataRow = DataRow & DataGridView1.Rows(i).Cells(k).Value ' last column dont put , separate
End If
DataRow = DataRow & DataGridView1.Rows(i).Cells(k).Value & ","
Next
file.WriteLine(DataRow)
DataRow = ""
Next
loopend:
file.Close()
End Sub