Vb.net crystal report not displaying the items - sql

I am trying to display all of the purchases in an inventory system but it is not displaying in my crystal report PS: this my first time using Crystal Report
here's my code:
Dim show As String = String.Empty
show &= "select * from purchase_report "
show &= "where buildnumber=#build"
Using conn As New SqlConnection("Server=WIN10;database=purchase_stock;user=admin_report;password=54321")
Using cmd As New SqlCommand
With cmd
.Connection = conn
.CommandType = CommandType.Text
.CommandText = show
.Parameters.AddWithValue("#build", report.Text)
End With
Try
conn.Open()
Dim da As New SqlDataAdapter(cmd)
Dim ds As New DataSet
da.Fill(ds)
If ds.Tables.Count > 0 Then
CrystalReportViewer1.ReportSource = ds.Tables.Count
End If
conn.Close()
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Using
End Using
End Sub
End Class

Try this code :
Change it as per your needs
Friend Function ViewReport(ByVal sReportName As String, _
Optional ByVal sSelectionFormula As String = "", _
Optional ByVal param As String = "") As Boolean
'Declaring variables
Dim intCounter As Integer
Dim intCounter1 As Integer
'Crystal Report's report document object
Dim objReport As New _
CrystalDecisions.CrystalReports.Engine.ReportDocument
'object of table Log on info of Crystal report
Dim ConInfo As New CrystalDecisions.Shared.TableLogOnInfo
'Parameter value object of crystal report
' parameters used for adding the value to the parameter.
Dim paraValue As New CrystalDecisions.Shared.ParameterDiscreteValue
'Current parameter value object(collection) of crystal report parameters.
Dim currValue As CrystalDecisions.Shared.ParameterValues
'Subreport object of crystal report.
Dim mySubReportObject As _
CrystalDecisions.CrystalReports.Engine.SubreportObject
'Sub report document of crystal report.
Dim mySubRepDoc As New _
CrystalDecisions.CrystalReports.Engine.ReportDocument
Dim strParValPair() As String
Dim strVal() As String
Dim index As Integer
Try
'Load the report
objReport.Load(sReportName)
'Check if there are parameters or not in report.
intCounter = objReport.DataDefinition.ParameterFields.Count
'As parameter fields collection also picks the selection
' formula which is not the parameter
' so if total parameter count is 1 then we check whether
' its a parameter or selection formula.
If intCounter = 1 Then
If InStr(objReport.DataDefinition.ParameterFields(_
0).ParameterFieldName, ".", CompareMethod.Text) > 0 Then
intCounter = 0
End If
End If
'If there are parameters in report and
'user has passed them then split the
'parameter string and Apply the values
'to their concurrent parameters.
If intCounter > 0 And Trim(param) <> "" Then
strParValPair = param.Split("&")
For index = 0 To UBound(strParValPair)
If InStr(strParValPair(index), "=") > 0 Then
strVal = strParValPair(index).Split("=")
paraValue.Value = strVal(1)
currValue = _
objReport.DataDefinition.ParameterFields(_
strVal(0)).CurrentValues
currValue.Add(paraValue)
objReport.DataDefinition.ParameterFields(_
strVal(0)).ApplyCurrentValues(currValue)
End If
Next
End If
'Set the connection information to ConInfo
'object so that we can apply the
'connection information on each table in the report
ConInfo.ConnectionInfo.UserID = <User Name>
ConInfo.ConnectionInfo.Password = <Password>
ConInfo.ConnectionInfo.ServerName = <Server Name>
ConInfo.ConnectionInfo.DatabaseName = <Database Name>
For intCounter = 0 To objReport.Database.Tables.Count - 1
objReport.Database.Tables(intCounter).ApplyLogOnInfo(ConInfo)
Next
' Loop through each section of the report then look
' through each object in the section
' if the object is a subreport, then apply login info
' on each table of that subreport
For index = 0 To objReport.ReportDefinition.Sections.Count - 1
For intCounter = 0 To _
objReport.ReportDefinition.Sections(_
index).ReportObjects.Count - 1
With objReport.ReportDefinition.Sections(index)
If .ReportObjects(intCounter).Kind = _
CrystalDecisions.Shared.ReportObjectKind.SubreportObject Then
mySubReportObject = CType(.ReportObjects(intCounter), _
CrystalDecisions.CrystalReports.Engine.SubreportObject)
mySubRepDoc = _
mySubReportObject.OpenSubreport(mySubReportObject.SubreportName)
For intCounter1 = 0 To mySubRepDoc.Database.Tables.Count - 1
mySubRepDoc.Database.Tables(_
intCounter1).ApplyLogOnInfo(_
ConInfo)sp;
mySubRepDoc.Database.Tables(_
intCounter1).ApplyLogOnInfo(ConInfo)
Next
End If
End With
Next
Next
'If there is a selection formula passed to this function then use that
If sSelectionFormula.Length > 0 Then
objReport.RecordSelectionFormula = sSelectionFormula
End If
'Re setting control
rptViewer.ReportSource = Nothing
'Set the current report object to report.
rptViewer.ReportSource = objReport
'Show the report
rptViewer.Show()
Return True
Catch ex As System.Exception
MsgBox(ex.Message)
End Try
End Function

Related

Deleting multiple records from sql bound Datagrid

The procedures below allowed me to delete several records at once by checking the checkbox on my datagrid. The procedure was written on ASP.net but now I am using a winform on VB.net.
I have a datagrid with column name "Delete" where the checkboxes are located. The user would check
the records it wants to delete and the would delete those records. I use the "Ticket Number" column values as the parameter for my query.
The issue I have is that since was written for ASP.Net, I cannot find how the winform VB.net equivalent for this line:
Dim chkDelete As CheckBox = DirectCast(grdRoster.Rows(i).Cells(0).FindControl("Delete_Row"), CheckBox)
FindControl is not a member of System.Windows.Forms.DataGridViewCell. Plus I am pretty sure that the whole line is wrong since the checkboxes
are located on a datagrid column set as ColumnType: DataGridViewCheckBoxColumn and are not really individual controls.
How can I get the same result on a winform? Here is my entire code.
Private Sub btnDelete_Click(sender As Object, e As EventArgs) Handles btnDelete.Click
'Create String Collection to store
'IDs of records to be deleted
Dim ticketNumberCollection As New StringCollection()
Dim strTicketNumber As String = String.Empty
'Loop through GridView rows to find checked rows
For i As Integer = 0 To grdRoster.Rows.Count - 1
Dim chkDelete As CheckBox = DirectCast(grdRoster.Rows(i).Cells(0).FindControl("Delete_Row"), CheckBox)
If chkDelete IsNot Nothing Then
If chkDelete.Checked Then
strTicketNumber = grdRoster.Rows(i).Cells(1).ToString
ticketNumberCollection.Add(strTicketNumber)
End If
End If
Next
'Call the method to Delete records
DeleteMultipleRecords(ticketNumberCollection)
' rebind the GridView
grdRoster.DataBind()
End Sub
' Sub to delete multiple records
' #param "idCollection" calls the string collection above
' and deletes the selected record separated by ","
Private Sub DeleteMultipleRecords(ByVal ticketNumberCollection As StringCollection)
Dim IDs As String = ""
'Create string builder to store
'delete commands separated by ,
For Each id As String In ticketNumberCollection
IDs += id.ToString() & ","
Next
Try
Dim strTicketID As String = IDs.Substring(0, IDs.LastIndexOf(","))
DataSheetTableAdapter.DeleteRecord(strTicketID)
Catch ex As Exception
Dim errorMsg As String = "Error in Deletion"
errorMsg += ex.Message
Throw New Exception(errorMsg)
Finally
Me.Close()
End Try
End Sub
for deleting multiple records from a data bound gridview you should create the DataGridViewCheckBoxColumn at run time
Dim chk As New DataGridViewCheckBoxColumn()
DataGridView1.Columns.Add(chk)
chk.HeaderText = "Select"
'then bind your datagridview with dataset
Dim sql As String = "SELECT * FROM table_name"
' Dim connection As New SqlConnection(connectionString)
conn.Open()
sCommand = New SqlCommand(sql, conn)
sAdapter = New SqlDataAdapter(sCommand)
sBuilder = New SqlCommandBuilder(sAdapter)
sDs = New DataSet()
sAdapter.Fill(sDs, "table_name")
sTable = sDs.Tables("table_name")
DataGridView1.DataSource = sDs.Tables("table_name")
'then traverse through each column and get the checked values
Try
DataGridView1.EndEdit()
For j = Me.DataGridView1.Rows.Count - 1 To 0 Step -1
If Not IsDBNull(DataGridView1.Rows(j).Cells(0).Value) Then
If DataGridView1.Rows(j).Cells(0).Value = True Then
check = True
If MessageBox.Show("Do you want to delete these records?", "Delete", MessageBoxButtons.YesNo) = DialogResult.Yes Then
For i = Me.DataGridView1.Rows.Count - 1 To 0 Step -1
If Not IsDBNull(DataGridView1.Rows(i).Cells(0).Value) Then
If DataGridView1.Rows(i).Cells(0).Value = True Then
'remove the checked columns and update datatable
DataGridView1.Rows.RemoveAt(i)
sAdapter.Update(sTable)
End If
End If
Next
Else
Return
End If
Else
End If
End If
Next
If check = False Then
MsgBox("Nothing Selected")
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Try

VB.Net Global DataSets inside a public function

I am having some problem with a function that I hope you can help.
My Application is a simple one, it uses an Access database to load employee information and creates letters and financial breakdown sheet from word templates that users can then print and save back to the database.
I started by creating a dataset containing several datatables for each form subroutine but it resulted in literally hundreds of lines of repeated code. But it worked.
What I want to do, is have one dataset containing all the information needed about an employee and be able to reference it over several forms at the same time. So i created a public module that looks like this:
Public Module Datasets
Public update As String
Dim pCn As OleDb.OleDbConnection
Public Function CSofwareDataSet() As DataSet
'open new connection to database
pCn = New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=G:\CGI Project\CorrespondenceSoftware\Database1.accdb; Persist Security Info=False;")
Try
Call pCn.Open() 'opens the connection
Catch ex As Exception
MessageBox.Show("Could not open a database connection! 1")
MessageBox.Show(ex.ToString)
End Try
CSofwareDataSet = New DataSet
Dim daOPG As New OleDb.OleDbDataAdapter("SELECT * FROM Overpayment WHERE PayNumber='" & Main.tbPayNumber.Text & "' AND Gross=1", pCn) 'get all data from Overpayment Details table
Dim daOPN As New OleDb.OleDbDataAdapter("SELECT * FROM Overpayment WHERE PayNumber='" & Main.tbPayNumber.Text & "' AND Net=1", pCn) 'get all data from Overpayment Details table
Dim daOPR As New OleDb.OleDbDataAdapter("SELECT * FROM OvpReasons", pCn) 'get overpayment reasons
Dim daREC As New OleDb.OleDbDataAdapter("SELECT * FROM TaxYear", pCn) 'get recovery date options
Dim daEMP As New OleDb.OleDbDataAdapter("SELECT * FROM EmployeeDetails WHERE PayNumber='" & Main.tbPayNumber.Text & "' AND Active=1 ", pCn) 'get all data from Employee Details table
Dim daCON As New OleDb.OleDbDataAdapter("SELECT * FROM Consultant", pCn) 'get all data from Consultant Details table
Dim daSET As New OleDb.OleDbDataAdapter("SELECT * FROM Settings", pCn) 'get all data from Consultant Details table
'Find the primary key (if missing)
daOPG.MissingSchemaAction = MissingSchemaAction.AddWithKey
daOPN.MissingSchemaAction = MissingSchemaAction.AddWithKey
daOPR.MissingSchemaAction = MissingSchemaAction.AddWithKey
daREC.MissingSchemaAction = MissingSchemaAction.AddWithKey
daEMP.MissingSchemaAction = MissingSchemaAction.AddWithKey
daCON.MissingSchemaAction = MissingSchemaAction.AddWithKey
daSET.MissingSchemaAction = MissingSchemaAction.AddWithKey
'setup prefixes
Dim cbOPG As New OleDb.OleDbCommandBuilder(daOPG)
cbOPG.QuotePrefix = "["
cbOPG.QuoteSuffix = "]"
Dim cbOPN As New OleDb.OleDbCommandBuilder(daOPN)
cbOPG.QuotePrefix = "["
cbOPG.QuoteSuffix = "]"
Dim cbOPR As New OleDb.OleDbCommandBuilder(daOPR)
cbOPG.QuotePrefix = "["
cbOPG.QuoteSuffix = "]"
Dim cbREC As New OleDb.OleDbCommandBuilder(daREC)
cbOPG.QuotePrefix = "["
cbOPG.QuoteSuffix = "]"
Dim cbEMP As New OleDb.OleDbCommandBuilder(daEMP)
cbEMP.QuotePrefix = "["
cbEMP.QuoteSuffix = "]"
Dim cbCON As New OleDb.OleDbCommandBuilder(daCON)
cbEMP.QuotePrefix = "["
cbEMP.QuoteSuffix = "]"
Dim cbSET As New OleDb.OleDbCommandBuilder(daSET)
cbEMP.QuotePrefix = "["
cbEMP.QuoteSuffix = "]"
If CSofwareDataSet.HasChanges Then
Try
daEMP.Update(CSofwareDataSet, "EmployeeDetails")
daOPG.Update(CSofwareDataSet, "OverPaymentGross")
daOPN.Update(CSofwareDataSet, "OverPaymentNet")
daSET.Update(CSofwareDataSet, "Settings")
MessageBox.Show("Success! Records updated.")
update = "0"
Catch ex As Exception
MessageBox.Show("Oops - something went wrong and it didn't update")
update = "0"
End Try
ElseIf CSofwareDataSet.Tables.Count = 0 Then
daOPG.Fill(CSofwareDataSet, "OverPaymentGross")
daOPN.Fill(CSofwareDataSet, "OverPaymentNet")
daOPR.Fill(CSofwareDataSet, "OverPaymentReasons")
daREC.Fill(CSofwareDataSet, "RecoveryDates")
daEMP.Fill(CSofwareDataSet, "EmployeeDetails")
daCON.Fill(CSofwareDataSet, "ConsultantDetails")
daSET.Fill(CSofwareDataSet, "Settings")
End If
'If update = "1" Then
' Try
' daEMP.Update(CSofwareDataSet, "EmployeeDetails")
' daOPG.Update(CSofwareDataSet, "OverPaymentGross")
' daOPN.Update(CSofwareDataSet, "OverPaymentNet")
' daSET.Update(CSofwareDataSet, "Settings")
'
' MessageBox.Show("Success! Records updated.")
' update = "0"
' Catch ex As Exception
' MessageBox.Show("Oops - something went wrong and it didn't update")
' update = "0"
' End Try
' End If
pCn.Close()
End Function
End Module
On each form, it gets referenced like this (as an example):
Imports WeifenLuo.WinFormsUI.Docking
Imports Word = Microsoft.Office.Interop.Word
Imports CorrespondenceSoftware.Datasets
Public Class GrossInput
Dim loading = "1"
Dim NewEmployee = "0" 'sets the default new employee flag to 0
Private pCn As OleDb.OleDbConnection
Private Sub GrossInput_Load(ByVal Sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Try
Try
If CSofwareDataSet.Tables("EmployeeDetails").Rows.Count > 0 Then
For i As Integer = 0 To CSofwareDataSet.Tables("EmployeeDetails").Rows.Count - 1
cbTitle.Text = CSofwareDataSet.Tables("EmployeeDetails").Rows(i)(2)
tbFName.Text = CSofwareDataSet.Tables("EmployeeDetails").Rows(i)(3)
tbLName.Text = CSofwareDataSet.Tables("EmployeeDetails").Rows(i)(4)
tbAddress1.Text = CSofwareDataSet.Tables("EmployeeDetails").Rows(i)(5)
tbAddress2.Text = CSofwareDataSet.Tables("EmployeeDetails").Rows(i)(6)
tbAddress3.Text = CSofwareDataSet.Tables("EmployeeDetails").Rows(i)(7)
tbAddress4.Text = CSofwareDataSet.Tables("EmployeeDetails").Rows(i)(8)
tbPostcode.Text = CSofwareDataSet.Tables("EmployeeDetails").Rows(i)(9)
tbWorkLocation.Text = CSofwareDataSet.Tables("EmployeeDetails").Rows(i)(10)
tbWorkLocation.Enabled = False
tbPostcode.Enabled = False
tbAddress4.Enabled = False
tbAddress3.Enabled = False
tbAddress2.Enabled = False
tbAddress1.Enabled = False
tbLName.Enabled = False
tbFName.Enabled = False
cbTitle.Enabled = False
chkMSC.Enabled = False
chkOfficer.Enabled = False
chkStaff.Enabled = False
bnSaveEmp.Enabled = False
bnEditEmp.Enabled = True
Next
End If
If CSofwareDataSet.Tables("EmployeeDetails").Rows(0)(11) = "1" Then
chkOfficer.Checked = True
Else
chkOfficer.Checked = False
End If
If CSofwareDataSet.Tables("EmployeeDetails").Rows(0)(12) = "1" Then
chkStaff.Checked = True
Else
chkStaff.Checked = False
End If
If CSofwareDataSet.Tables("EmployeeDetails").Rows(0)(13) = "1" Then
chkMSC.Checked = True
Else
chkMSC.Checked = False
End If
Catch ex As Exception
MessageBox.Show(ex.ToString)
MessageBox.Show("Employee not found. Ensure pay number is correct and create a new record")
NewEmployee = "1" ' tells the program to create a new record if saved
cbReference.Enabled = False
cbReference.Text = ""
bnEditEmp.Enabled = False
End Try
'display the overpayment references to the user
If CSofwareDataSet.Tables("OverPaymentGross").Rows.Count > 0 Then
For i As Integer = 0 To CSofwareDataSet.Tables("OverPaymentGross").Rows.Count - 1
cbReference.Items.Add(CSofwareDataSet.Tables("OverPaymentGross").Rows(i)(2))
Next
End If
'display the available consultants to the user
If CSofwareDataSet.Tables("ConsultantDetails").Rows.Count > 0 Then
For i As Integer = 0 To CSofwareDataSet.Tables("ConsultantDetails").Rows.Count - 1
cbConsultant.Items.Add(CSofwareDataSet.Tables("ConsultantDetails").Rows(i)(1) & " " & CSofwareDataSet.Tables("ConsultantDetails").Rows(i)(2))
Next
End If
'display the available Overpayment reasons to the user
If CSofwareDataSet.Tables("OverPaymentReasons").Rows.Count > 0 Then
For i As Integer = 0 To CSofwareDataSet.Tables("OverPaymentReasons").Rows.Count - 1
cbReason.Items.Add(CSofwareDataSet.Tables("OverPaymentReasons").Rows(i)(1))
Next
End If
'Load other recovery date options
If CSofwareDataSet.Tables("RecoveryDates").Rows.Count > 0 Then
For i As Integer = 0 To CSofwareDataSet.Tables("RecoveryDates").Rows.Count - 1
cbStartRecovery.Items.Add(CSofwareDataSet.Tables("RecoveryDates").Rows(i)(1))
Next
End If
Catch ex As Exception
MessageBox.Show(ex.ToString) 'Show any errors to the user
End Try
loading = "0"
End Sub
Now! the problem that I'm having is that, this does work and run without any errors BUT every time the CSSoftwareDataSet function runs it populates the tables correctly and returns the expected results but it then deletes the datatable data so every time the function is referenced from a winform it needs to haul all the data from the access database from scratch, severely impacting on the performance of the program. The tables wont update properly because its not storing the datatable information and as soon as its inserted its forgotten but again, produces no errors. An example of my update script looks like this:
Else 'create a new record
'create a new reference
Dim REFRowCount = CSofwareDataSet.Tables("OverPaymentGross").Rows.Count + 1 'count the number of rows in table and add 1
Dim NewREF = "OVPG" & Main.tbPayNumber.Text & "-" & REFRowCount
'Find todays date and reply dates
Dim TodayDatedate = Format(Now.Date(), "dd/MM/yyyy")
Dim ReplyDatedate = Format(Now.Date.AddDays(21), "dd/MM/yyyy")
'Create a new row
Dim OPNew As DataRow = CSofwareDataSet.Tables("OverPaymentGross").NewRow() 'create a variable to contain the new row
OPNew.Item(1) = Main.tbPayNumber.Text
OPNew.Item(2) = NewREF
OPNew.Item(3) = tbOverpaymentAmount.Text.ToString
OPNew.Item(4) = tbMonRec.Text
OPNew.Item(5) = tbTaxP.Text
OPNew.Item(6) = TodayDatedate
OPNew.Item(7) = ReplyDatedate
OPNew.Item(8) = tbMoRep.Text
OPNew.Item(9) = cbStartRecovery.Text
OPNew.Item(10) = "1" 'Set as gross
OPNew.Item(11) = "0" 'do not set as net
OPNew.Item(12) = cbReason.Text
OPNew.Item(13) = tbAI.Text
OPNew.Item(14) = dtpStart.Value.Date
OPNew.Item(15) = dtpFinish.Value.Date
OPNew.Item(16) = cbConsultant.Text
OPNew.Item(17) = tbPosition.Text
Call CSofwareDataSet.Tables("OverPaymentGross").Rows.Add(OPNew) 'fill the new row and insert the data
There must be a solution to this. To create a dataset that holds its data in session while you open other winforms until it is reset. I'm out of ideas because i really don't want to go back to repeating all this code for practically every subroutine in my program.
I hope I've explained it OK .. Any help here will be greatly appreciated.
Many thanks,
Shane
You can declare the DataSet globally, populate it in a function (sub), which is called just at the start, and retrieve the information by accessing the variable rather than by calling the function over and over. Your code uses a somehow ambiguous approach (same name for function and for variable) which, together with the VB rules (functions might not include a Return statement but a variable with the function's name) does not play to your favor.
Sample code converting the DataSet into a public variable and renaming the function (and converting it into a sub: what is the point of a function now?):
Public CSofwareDataSet As DataSet
Public Sub populateDS()
'open new connection to database
pCn = New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=G:\CGI Project\CorrespondenceSoftware\Database1.accdb; Persist Security Info=False;")
Try
Call pCn.Open() 'opens the connection
Catch ex As Exception
MessageBox.Show("Could not open a database connection! 1")
MessageBox.Show(ex.ToString)
End Try
CSofwareDataSet = New DataSet
'Remaining code
End Sub
Call this sub just once (right at the start of your application; or every time new data has to be retrieved from the DB) and continue using CSofwareDataSet as so far (although as a variable, by removing the Call bits; which, on the other hand, are not required in VB.NET at all).

Fast Export of Large Datatable to Excel Spreadsheet in VB.Net

I have an interesting conundrum here, how do I quickly (under 1 minute) export a large datatable (filled from SQL, 35,000 rows) into an Excel spreadsheet for users. I have code in place that can handle the export, and while nothing is "wrong" with the code per se, it is infuriatingly slow taking 4 minutes to export the entire file (sometimes longer if a user has less RAM or is running more on their system). Sadly, this is an improvement over the 10+ minutes it used to take using our old method. Simply put, can this be made any faster, without using 3rd party components? If so, how? My code is as follows, the slow down occurs between messageboxes 6 and 7 where each row is written. Thank you all for taking the time to take a look at this:
Private Sub btnTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnJeffTest.Click
Test(MySPtoExport)
End Sub
Private Sub Test(ByVal SQL As String)
'Declare variables used to execute the VUE Export stored procedure
MsgBox("start stop watch")
Dim ConnectionString As New SqlConnection(CType(ConfigurationManager.AppSettings("ConnString"), String))
Dim cmdSP As New SqlClient.SqlCommand
Dim MyParam As New SqlClient.SqlParameter
Dim MyDataAdapter As New SqlClient.SqlDataAdapter
Dim ExportDataSet As New DataTable
Dim FilePath As String
MsgBox("stop 1 - end of declare")
Try
' open the connection
ConnectionString.Open()
' Use the connection for this sql command
cmdSP.Connection = ConnectionString
'set this command as a stored procedure command
cmdSP.CommandType = CommandType.StoredProcedure
'get the stored procedure name and plug it in
cmdSP.CommandText = SQL
'Add the Start Date parameter if required
Select Case StDt
Case Nothing
' there's no parameter to add
Case Is = 0
' there's no parameter to add
Case Else
'add the parameter name, it's direction and its value
MyParam = cmdSP.Parameters.Add("#StartDate", SqlDbType.VarChar)
MyParam.Direction = ParameterDirection.Input
MyParam.Value = Me.txtStartDate.Text
End Select
MsgBox("stop 2 - sql ready")
'Add the End Date parameter if required
Select Case EdDt
Case Nothing
' there's no parameter to add
Case Is = 0
' there's no parameter to add
Case Else
'add the parameter name, it's direction and its value
MyParam = cmdSP.Parameters.Add("#EndDate", SqlDbType.VarChar)
MyParam.Direction = ParameterDirection.Input
MyParam.Value = Me.txtEndDate.Text
End Select
'Add the single parameter 1 parameter if required
Select Case SPar1
Case Is = Nothing
' there's no parameter to add
Case Is = ""
' there's no parameter to add
Case Else
'add the parameter name, it's direction and its value
MyParam = cmdSP.Parameters.Add(SPar1, SqlDbType.VarChar)
MyParam.Direction = ParameterDirection.Input
MyParam.Value = Me.txtSingleReportCrt1.Text
End Select
'Add the single parameter 2 parameter if required
Select Case Spar2
Case Is = Nothing
' there's no parameter to add
Case Is = ""
' there's no parameter to add
Case Else
'add the parameter name, it's direction and its value
MyParam = cmdSP.Parameters.Add(Spar2, SqlDbType.VarChar)
MyParam.Direction = ParameterDirection.Input
MyParam.Value = Me.txtSingleReportCrt2.Text
End Select
MsgBox("stop 3 - params ready")
'Prepare the data adapter with the selected command
MyDataAdapter.SelectCommand = cmdSP
' Set the accept changes during fill to false for the NYPDA export
MyDataAdapter.AcceptChangesDuringFill = False
'Fill the Dataset tables (Table 0 = Exam Eligibilities, Table 1 = Candidates Demographics)
MyDataAdapter.Fill(ExportDataSet)
'Close the connection
ConnectionString.Close()
'refresh the destination path in case they changed it
SPDestination = txtPDFDestination.Text
MsgBox("stop 4 - procedure ran, datatable filled")
Select Case ExcelFile
Case True
FilePath = SPDestination & lblReportName.Text & ".xls"
Dim _excel As New Microsoft.Office.Interop.Excel.Application
Dim wBook As Microsoft.Office.Interop.Excel.Workbook
Dim wSheet As Microsoft.Office.Interop.Excel.Worksheet
wBook = _excel.Workbooks.Add()
wSheet = wBook.ActiveSheet()
Dim dt As System.Data.DataTable = ExportDataSet
Dim dc As System.Data.DataColumn
Dim dr As System.Data.DataRow
Dim colIndex As Integer = 0
Dim rowIndex As Integer = 0
MsgBox("stop 5 - excel stuff declared")
For Each dc In dt.Columns
colIndex = colIndex + 1
_excel.Cells(1, colIndex) = dc.ColumnName
Next
MsgBox("stop 6 - Header written")
For Each dr In dt.Rows
rowIndex = rowIndex + 1
colIndex = 0
For Each dc In dt.Columns
colIndex = colIndex + 1
_excel.Cells(rowIndex + 1, colIndex) = dr(dc.ColumnName)
Next
Next
MsgBox("stop 7 - rows written")
wSheet.Columns.AutoFit()
MsgBox("stop 8 - autofit complete")
Dim strFileName = SPDestination & lblReportName.Text & ".xls"
If System.IO.File.Exists(strFileName) Then
System.IO.File.Delete(strFileName)
End If
MsgBox("stop 9 - file checked")
wBook.SaveAs(strFileName)
wBook.Close()
_excel.Quit()
End Select
MsgBox("File " & lblReportName.Text & " Exported Successfully!")
'Dispose of unneeded objects
MyDataAdapter.Dispose()
ExportDataSet.Dispose()
StDt = Nothing
EdDt = Nothing
SPar1 = Nothing
Spar2 = Nothing
MyParam = Nothing
cmdSP.Dispose()
cmdSP = Nothing
MyDataAdapter = Nothing
ExportDataSet = Nothing
Catch ex As Exception
' Something went terribly wrong. Warn user.
MessageBox.Show("Error: " & ex.Message, "Stored Procedure Running Process ", _
MessageBoxButtons.OK, MessageBoxIcon.Error)
Finally
'close the connection in case is still open
If Not ConnectionString.State = ConnectionState.Closed Then
ConnectionString.Close()
ConnectionString = Nothing
End If
' reset the fields
ResetFields()
End Try
End Sub
Even though the question was asked several years ago, I thought I would add my solution since the question was posed in VB and the "best answer" is in C#. This solution writes 22,000+ rows (1.9MB) in 4 seconds on an i7 System w/ 16GB RAM.
Imports Excel = Microsoft.Office.Interop.Excel
Public Class Main
Private Sub btnExportToExcel(sender As Object, e As EventArgs) Handles btnExpToExcel.Click
'Needed for the Excel Workbook/WorkSheet(s)
Dim app As New Excel.Application
Dim wb As Excel.Workbook = app.Workbooks.Add()
Dim ws As Excel.Worksheet
Dim strFN as String = "MyFileName.xlsx" 'must have ".xlsx" extension
'Standard code for filling a DataTable from SQL Server
Dim strSQL As String = "My SQL Statement for the DataTable"
Dim conn As New SqlConnection With {.ConnectionString = "My Connection"}
Dim MyTable As New DataTable
Dim cmd As New SqlCommand(strSQL, conn)
Dim da As New SqlDataAdapter(cmd)
da.Fill(MyTable)
'Add a sheet to the workbook and fill it with data from MyTable
'You could create multiple tables and add additional sheets in a loop
ws = wb.Sheets.Add(After:=wb.Sheets(wb.Sheets.Count))
DataTableToExcel(MyTable, ws, strSym)
wb.SaveAs(strFN) 'save and close the WorkBook
wb.Close()
MsgBox("Export complete.")
End Sub
Private Sub DataTableToExcel(dt As DataTable, ws As Excel.Worksheet, TabName As String)
Dim arr(dt.Rows.Count, dt.Columns.Count) As Object
Dim r As Int32, c As Int32
'copy the datatable to an array
For r = 0 To dt.Rows.Count - 1
For c = 0 To dt.Columns.Count - 1
arr(r, c) = dt.Rows(r).Item(c)
Next
Next
ws.Name = TabName 'name the worksheet
'add the column headers starting in A1
c = 0
For Each column As DataColumn In dt.Columns
ws.Cells(1, c + 1) = column.ColumnName
c += 1
Next
'add the data starting in cell A2
ws.Range(ws.Cells(2, 1), ws.Cells(dt.Rows.Count, dt.Columns.Count)).Value = arr
End Sub
End Class
Hope it helps.
As when using VBA to automate Excel, you can assign an array directly to the value of a Range object: this is done as a single operation, so you remove the overhead associated with making multiple calls across the process boundaries between your .Net code and the Excel instance.
Eg, see the accepted answer here: Write Array to Excel Range
The answer from CPRouse worked for me except that it left off the last row of data. In the Private Sub DataTableToExcel function, I added 1 to the rows.count on this line and it wrote all the records. ws.Range(ws.Cells(2, 1), ws.Cells(dt.Rows.Count + 1, dt.Columns.Count)).Value = arr
Here is a piece of my own code that performs a very fast export of data from a DataTable to an Excel sheet (use the "Stopwatch" object to compare the speed and let me a comment):
Dim _excel As New Excel.Application
Dim wBook As Excel.Workbook
Dim wSheet As Excel.Worksheet
wBook = _excel.Workbooks.Add()
wSheet = wBook.ActiveSheet()
Dim dc As System.Data.DataColumn
Dim colIndex As Integer = 0
Dim rowIndex As Integer = 0
'Nombre de mesures
Dim Nbligne As Integer = DtMesures.Rows.Count
'Ecriture des entêtes de colonne et des mesures
'(Write column headers and data)
For Each dc In DtMesures.Columns
colIndex = colIndex + 1
'Entête de colonnes (column headers)
wSheet.Cells(1, colIndex) = dc.ColumnName
'Données(data)
'You can use CDbl instead of Cobj If your data is of type Double
wSheet.Cells(2, colIndex).Resize(Nbligne, ).Value = _excel.Application.transpose(DtMesures.Rows.OfType(Of DataRow)().[Select](Function(k) CObj(k(dc.ColumnName))).ToArray())
Next
We had a VB.NET app that did exactly this, and took even longer for our users who were on slow PC's... sometimes 15 minutes.
The app is now an ASP/VB.NET app which simply builds an HTML table and outputs the result as an .xls extension... excel is able to read the HTML table and parse it into a grid format. You can still pass in XML for formatting and options, horizontal pane locking, etc.
If you don't have the option of using ASP.NET... try looking into a way to build an HTML table string and have excel parse & populate for you... much faster! I'm sure excel can parse other types as well.... XML, Arrays, HTML, etc... all would be quicker than manually building each row through VB.NET objects.

Why do I get the error: System.Runtime.InteropServices.COMException?

I am using VB.NET to Create Labels in Microsoft. This is my code:
Public Sub CreateLabel(ByVal StrFilter As String, ByVal Path As String)
WordApp = CreateObject("Word.Application")
''Add a new document.
WordDoc = WordApp.Documents.Add()
Dim oConn As SqlConnection = New SqlConnection(connSTR)
oConn.Open()
Dim oCmd As SqlCommand
Dim oDR As SqlDataReader
oCmd = New SqlCommand(StrFilter, oConn)
oDR = oCmd.ExecuteReader
Dim intI As Integer
Dim FilePath As String = ""
With WordDoc.MailMerge
With .Fields
Do While oDR.Read
For intI = 0 To oDR.FieldCount - 1
.Add(WordApp.Selection.Range, oDR.Item(intI))
Next
Loop
End With
Dim objAutoText As Word.AutoTextEntry = WordApp.NormalTemplate.AutoTextEntries.Add("MyLabelLayout", WordDoc.Content)
WordDoc.Content.Delete()
.MainDocumentType = Word.WdMailMergeMainDocType.wdMailingLabels
FilePath = CreateSource(StrFilter)
.OpenDataSource(FilePath)
Dim NewLabel As Word.CustomLabel = WordApp.MailingLabel.CustomLabels.Add("MyLabel", False)
WordApp.MailingLabel.CreateNewDocument(Name:="MyLabel", Address:="", AutoText:="MyLabelLayout")
objAutoText.Delete()
.Destination = Word.WdMailMergeDestination.wdSendToNewDocument
WordApp.Visible = True
.Execute()
End With
oConn.Close()
WordDoc.Close()
End Sub
Private Function CreateSource(ByVal StrFilter As String) As String
Dim CnnUser As SqlConnection = New SqlConnection(connSTR)
Dim sw As StreamWriter = File.CreateText("C:\Mail.Txt")
Dim Path As String = "C:\Mail.Txt"
Dim StrHeader As String = ""
Try
Dim SelectCMD As SqlCommand = New SqlCommand(StrFilter, CnnUser)
Dim oDR As SqlDataReader
Dim IntI As Integer
SelectCMD.CommandType = CommandType.Text
CnnUser.Open()
oDR = SelectCMD.ExecuteReader
For IntI = 0 To oDR.FieldCount - 1
StrHeader &= oDR.GetName(IntI) & " ,"
Next
StrHeader = Mid(StrHeader, 1, Len(StrHeader) - 2)
sw.WriteLine(StrHeader)
sw.Flush()
sw.Close()
StrHeader = ""
Do While oDR.Read
For IntJ As Integer = 0 To oDR.FieldCount - 1
StrHeader &= oDR.GetString(IntJ) & " ,"
Next
Loop
StrHeader = Mid(StrHeader, 1, Len(StrHeader) - 2)
sw = File.AppendText(Path)
sw.WriteLine(StrHeader)
CnnUser.Close()
sw.Flush()
sw.Close()
Catch ex As Exception
MessageBox.Show(ex.Message, "TempID", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
Return Path
End Function
Now when I am running the program I am getting this error. I tried hard but not able to locate what could be the problem the error is:
System.Runtime.InteropServices.COMException -->Horizontal and vertical
pitch must be greater than or equal to the label width and height,
respectively.
Even though I tried to set the Horizontal and vertical pitch programatically it gives same error.
Make sure that you have a default printer set up for the user account that the application runs under. Might not be relevant but I have had various unusual problems following that omission.
Did you install the Office Primary Interop Assemblies? (Appropriately abbreviated to PIA)
Try this

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