Hi I'm using the following code to generate a CSV file containing data from a dataset. The CSV generates fine and a prompt box displays so that the user can either open or save the csv file. What I'm wondering is whether it's possible to save the CSV file?
Thanks for any help
Edited with solution (NB I don't need the prompt box to open as I'll be writing additional code to generate and save a number of files and then display links to them). This saves the dataset as a CSV on our server.
Protected Sub exportBtn_click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim ds1 As DataSet
ds1 = csvdownload.ReturnNewPledges()
Dim csv As New chartnew.csvhelper
Dim strData1 As String = csv.Export(ds1, True)
Dim todaydate As Date = Date.Now.Date
Dim todaystr As String = todaydate.ToString("ddMMyyyy")
Dim filename As String = todaystr & "_filename.csv"
Dim saveDir As String = "writedir\files\"
Dim appPath As String = Request.PhysicalApplicationPath
Dim filePath As String = appPath + saveDir + filename
Dim writer As New StreamWriter(filePath)
writer.Write(strData1)
writer.Close()
End Sub
Use a StreamWriter:
Dim SwFromFile As StreamWriter = New StreamWriter(fileName)
SwFromFile.Write(strData1)
SwFromFile.Flush()
SwFromFile.Close()
Related
I have a situation where I need to use an Excel Template and insert values, then allow the user to download the updated file. I have done this using ClosedXML but as it uses a non native format for xlsx, I get a format error when opening the downloaded document and the saved instance of the document looses all formatting from the template.
I need a solution that outputs a xlsx document that is a copy of the original template, formatting and all, with the additional inserted values. If necessary, I can make a temporary copy of the template on the server.
Is there a tool I can use for this purpose?
I ended up using OpenXML. I am using VB.Net for this project and as I found very little example code in VB (mostly java or c#), I will attach it so it can be used as a reference.
The really nice thing about it is the document you get out of it does not have any validation errors or anything and all sheet formatting (text justification, font face, etc) survives.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Dim path = Server.MapPath("~/ExcelTemplates/rfi.xlsx")
Dim templateBytes As Byte() = System.IO.File.ReadAllBytes(path)
Using templateStream As MemoryStream = New MemoryStream
templateStream.Write(templateBytes, 0, templateBytes.Length)
Using sheetInstance As SpreadsheetDocument = SpreadsheetDocument.Open(templateStream, True)
Dim worksheetPart As WorksheetPart = GetWorksheetPartByName(sheetInstance, "Sheet1")
If worksheetPart IsNot Nothing Then
'this writes "Test!!!" to cell C7
'Dim cell As Cell = GetCell(worksheetPart.Worksheet, "C", 7)
'cell.CellValue = New CellValue("Test!!!")
'another way of doing it
GetCell(worksheetPart.Worksheet, "C", 7).CellValue = New CellValue("Test12")
'this next line would change the cell's contents data type
'cell.DataType = New EnumValue(Of CellValues)(CellValues.String)
worksheetPart.Worksheet.Save()
templateStream.Position = 0
Using ms As MemoryStream = New MemoryStream
templateStream.CopyTo(ms)
Response.Buffer = True
Response.Clear()
Response.ContentType = "application/vnd.ms-excel"
Response.AppendHeader("Content-Disposition", "filename=RFI.xlsx")
ms.WriteTo(Response.OutputStream)
Response.End()
End Using
End If
End Using
End Using
End Sub
Private Shared Function GetWorksheetPartByName(ByVal document As SpreadsheetDocument, ByVal sheetName As String) As WorksheetPart
Dim sheets As IEnumerable(Of Sheet) = document.WorkbookPart.Workbook.GetFirstChild(Of Sheets)().Elements(Of Sheet)().Where(Function(s) s.Name = sheetName)
If sheets.Count() = 0 Then
Return Nothing
End If
Dim relationshipId As String = sheets.First().Id.Value
Dim worksheetPart As WorksheetPart = CType(document.WorkbookPart.GetPartById(relationshipId), WorksheetPart)
Return worksheetPart
End Function
Private Shared Function GetCell(ByVal worksheet As Worksheet, ByVal columnName As String, ByVal rowIndex As UInteger) As Cell
Dim row As Row = GetRow(worksheet, rowIndex)
If row Is Nothing Then Return Nothing
Return row.Elements(Of Cell)().Where(Function(c) String.Compare(c.CellReference.Value, columnName & rowIndex, True) = 0).First()
End Function
Private Shared Function GetRow(ByVal worksheet As Worksheet, ByVal rowIndex As UInteger) As Row
Return worksheet.GetFirstChild(Of SheetData)().Elements(Of Row)().Where(Function(r) CType(r.RowIndex, UInteger) = rowIndex).First()
End Function
I tried to import from Excel to a dataset and an error message occurred.
I'm studying this site http://vb.net-informations.com/excel-2007/vb.net_excel_oledb.htm
Imports System.Data
Imports System.Data.SqlClient
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Try
Dim MyConnection As System.Data.OleDb.OleDbConnection
Dim DtSet As DataSet
Dim MyCommand As System.Data.OleDb.OleDbDataAdapter
Dim Loc As String = Application.StartupPath() + "\Param\exceldata.xlsx"
Dim strCOleCon As String = "provider=Microsoft.Jet.OLEDB.4.0; Data Source='" + Loc.Trim + "';Extended Properties=Excel 8.0;"
MyConnection = New OleDb.OleDbConnection(strCOleCon)
MyCommand = New OleDb.OleDbDataAdapter("select * from [Sheet1$]", MyConnection)
MyCommand.TableMappings.Add("Table", "TestTable")
DtSet = New DataSet
MyCommand.Fill(DtSet)
DataGridView1.DataSource = DtSet.Tables(0)
MyConnection.Close()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
End Class
U can use third party EPPLUS which is freeware.Which can import excel file into data set and it also has many functionallities to manipulate the excel file
First off I believe your connection is incorrect, you have an xlsx file but the connection is set for xls.
BTW Not sure if this is a forms or asp project but sure looks like a forms project for windows thinking about your first tag indicating asp.net.
Excel can be tricky in regards to how the connection string is setup, do you want to just read, does the first row in the sheet have column names or data, is there mixed data in a column etc.
Here is a snippet I have used to make things easier with connection but be forewarned it's not fool-proof in that you need to set HDR and IMEX correctly in the connection,
Imports System.Data.OleDb
Module ExcelOleDbConnections
''' <summary>
''' Creates a connection string on read data from an excel file
''' </summary>
''' <param name="FileName"></param>
''' <param name="Header">Yes if first row is column-names, No if first row is data</param>
''' <param name="IMEX"></param>
''' <returns></returns>
''' <remarks>
''' See following page for clarification on extended properties
''' including IMEX. Ignore C# code.
''' http://www.codeproject.com/Articles/37055/Working-with-MS-Excel-xls-xlsx-Using-MDAC-and-Oled
''' </remarks>
<System.Diagnostics.DebuggerStepThrough()> _
Public Function ExcelConnectionString(
ByVal FileName As String,
Optional ByVal Header As String = "No",
Optional ByVal IMEX As Integer = 1) As String
Dim Builder As New OleDbConnectionStringBuilder
If IO.Path.GetExtension(FileName).ToUpper = ".XLS" Then
Builder.Provider = "Microsoft.Jet.OLEDB.4.0"
Builder.Add("Extended Properties", String.Format("Excel 8.0;IMEX={0};HDR={1};", IMEX, Header))
Else
Builder.Provider = "Microsoft.ACE.OLEDB.12.0"
Builder.Add("Extended Properties", String.Format("Excel 12.0;IMEX={0};HDR={1};", IMEX, Header))
End If
Builder.DataSource = FileName
Return Builder.ToString
End Function
End Module
Sample reading a sheet where the first row is data. Note I am using optional parameters so the last two use default values
Dim dt As New DataTable
' sheet has data in first row
Using cn As New OleDb.OleDbConnection With {.ConnectionString = ExcelConnectionString(Loc)}
Using cmd As New OleDb.OleDbCommand With {.Connection = cn, .CommandText = "select * from [Sheet1$]"}
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
End Using
This example we assume the first row are field/column names
Dim dt As New DataTable
' sheet has column names for first row
Using cn As New OleDb.OleDbConnection With {.ConnectionString = ExcelConnectionString(Loc, "Yes", 0)}
Using cmd As New OleDb.OleDbCommand With {.Connection = cn, .CommandText = "select * from [Sheet1$]"}
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
End Using
Populate the DataGridView
If dt.Rows.Count > 0 Then
DataGridView1.DataSource = dt
Else
'
' recover e.g. tell user there are no records in this sheet
'
End If
Example all together
Try
Dim Loc As String = IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Param\exceldata.xlsx")
If IO.File.Exists(Loc) Then
Dim dt As New DataTable
' sheet has column names for first row
Using cn As New OleDb.OleDbConnection With {.ConnectionString = ExcelConnectionString(Loc, "Yes", 0)}
Using cmd As New OleDb.OleDbCommand With {.Connection = cn, .CommandText = "select * from [Sheet1$]"}
cn.Open()
dt.Load(cmd.ExecuteReader)
End Using
End Using
If dt.Rows.Count > 0 Then
DataGridView1.DataSource = dt
Else
'
' recover e.g. tell user there are no records in this sheet
'
End If
End If
Catch ex As Exception
MessageBox.Show("TODO")
End Try
See my windows forms examples (yes I see asp.net in your tags)
Excel and OleDb basics to advance operations
I Tried to delete blank rows from excel using the code
Dim wb As New Workbook("d:\test\book1.xls")
Dim sheets As WorksheetCollection = wb.Worksheets
Dim sheet As Worksheet = sheets(0)
sheet.Cells.DeleteBlankRows()
wb.Save("d:\test\mybook.xls")
But i am getting syntax error.Any one know the Namespace requiered to do this?
Try
ApplicationClass excel = new ApplicationClass();
Microsoft.Office.Interop.Excel.Range cellToBeDeleted = (Range)excel.Cells[rowIndex, columnIndex];
cellToBeDeleted.Delete();
Include the following namespace
using Excel = Microsoft.Office.Interop.Excel;
Try This
-Add Reference (from COM section ) Micsrosoft Excel Object Library to your project
Imports Microsoft.Office.Interop.Excel
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
delBlankRows("d:\test\book1.xls", 1)
End Sub
Private Sub delBlankRows(ByVal excelFileName As String, sheetIndex As Integer)
Dim excel As Microsoft.Office.Interop.Excel.Application = New Microsoft.Office.Interop.Excel.Application
Dim fileName = excelFileName
Dim w As Workbook = excel.Workbooks.Open(fileName)
Dim r As Range = w.Worksheets(sheetIndex).UsedRange.EntireRow.SpecialCells(XlCellType.xlCellTypeBlanks)
r.Delete()
w.Save()
w.Close()
End Sub
End Class
I have a datatable being created with various inputs. Sometimes the resulting table is 35000+ rows. Currently, the datatable gets displayed onto a gridview. It loads fine after a couple minutes. Then, theres an option to export the gridview to an excel file. Everytime we have a large table to export, the conversion fails.
My goal is to bypass the gridview step and take the formatted table and put it directly into an excel file. Could also be a csv file if thats faster to write/load, as long as the data table is similar to the gridview output.
I tried the following code here Export DataTable to Excel File. I did my best to convert it to vb, here...
Protected Sub btnExportData_Click(sender As Object, e As EventArgs) Handles btnExportData.Click
Dim dt As DataTable
dt = CreateDataSource()
Dim filename As String = "attachment; filename=DistComplain.xls"
Response.ClearContent()
Response.AddHeader("content-disposition", filename)
Response.ContentType = "application/vnd.ms-excel"
Dim tab As String = ""
For Each dc As DataColumn In dt.Columns
Response.Write((tab + dc.ColumnName))
tab = "" & vbTab
Next
Response.Write("" & vbLf)
Dim i As Integer
For Each dr As DataRow In dt.Rows
tab = ""
i = 0
Do While (i < dt.Columns.Count)
Response.Write((tab + dr(i).ToString))
tab = "" & vbTab
i = (i + 1)
Loop
Response.Write("" & vbLf)
Next
Response.End()
End Sub
CreateDataSource() is the table that gets created in memory. Then theres other buttons that call it to fill the gridview. Right now it successfully complies and runs, and then it successfully creates the file. Although, when the file tries to open I get this error...
This happens when I try both xls and csv files. Something is not getting translated right. Any solutions?
(Written with help from Google) Create an export using the StringWriter class:
Public Shared Sub ExportDataSetToExcel(ds As DataSet, filename As String)
Dim response As HttpResponse = HttpContext.Current.Response
'Clean response object
response.Clear()
response.Charset = ""
'Set response header
response.ContentType = "application/vnd.ms-excel"
response.AddHeader("Content-Disposition", "attachment;filename=""" & filename & """")
'Create StringWriter and use to create CSV
Using sw As New StringWriter()
Using htw As New HtmlTextWriter(sw)
'Instantiate DataGrid
Dim dg As New DataGrid()
dg.DataSource = ds.Tables(0)
dg.DataBind()
dg.RenderControl(htw)
response.Write(sw.ToString())
response.[End]()
End Using
End Using
End Sub
You just need to pass the function the DataSet and the File Name. If you do not want to edit your CreateDataSource() function, you can merge it into a DataSet first like so:
Dim dt As DataTable = CreateDataSource()
Dim ds As New DataSet
ds.Merge(dt)
Your question is about why you're getting the message about being unable to open the file, correct?
According to Microsoft, this occurs when you have the "Ignore other applications that use Dynamic Data Exchange (DDE)" setting turned on. (See here). The link includes instructions to change the setting.
I want to render a report directly to pdf. I have an objectdatasource with 2 parameters. I obtain these parameters from a hiddenfield on the webform and from the datakeyname on a gridview. The report works when I load it in report viewer without rendering to pdf. When I place the code to render the report as pdf the parameters dont load i.e. the report renders as pdf but there are no details on the report. My code is below, any help appreciated. I placed the code in gridview_selectedindexchanged:
Protected Sub GridView1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles GridView1.SelectedIndexChanged
Dim ds1 As New seminarsTableAdapters.Sem1TableAdapter
Dim rdssem As New ReportDataSource("seminars.sem1TableAdapter", ds1.GetData(aid:=HiddenField1.Value, semid:=GridView1.SelectedDataKey.Value))
Dim reportsem As New LocalReport
reportsem.ReportPath = "Report1.rdlc"
Dim p1 As New ReportParameter("aid", HiddenField1.Value)
Dim p2 As New ReportParameter("semid", GridView1.SelectedDataKey.Value().ToString)
reportsem.SetParameters(New ReportParameter() {p1, p2})
reportsem.DataSources.Add(rdssem)
Me.ReportViewer1.LocalReport.Refresh()
Dim warnings As Warning() = Nothing
Dim streamids As String() = Nothing
Dim mimeType As String = Nothing
Dim encoding As String = Nothing
Dim extension As String = Nothing
Dim bytes As Byte()
bytes = ReportViewer1.LocalReport.Render("PDF", Nothing, mimeType, encoding, extension, streamids, warnings)
Response.Clear()
Response.ContentType = mimeType
Response.AddHeader("content-disposition", "attachment; filename=foo." + extension)
Response.BinaryWrite(bytes)
Response.End()
End Sub
I overlooked the following line of code:
Dim rdssem As New ReportDataSource("seminars.sem1TableAdapter", ds1.GetData(aid......
it shoud read:
Dim rdssem As New ReportDataSource("seminars.sem1", ds1.GetData(aid.....
Working fine now!
Thanks!