Hi
I am using an ASP.NET application and producing a report in excel page with .csv extension. However I would like to produce it with .xlsx etension.
The code I am currently using is as follows:
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnSubmit.Click
Dim sql As String
Dim strLine As String = ""
Dim attachment As String = "attachment; filename=PTW.csv"
m_sBranch = ddlBranches.SelectedValue
m_sRegion = ddlAreas.SelectedValue
Dim cnn As SqlConnection = New SqlConnection("Server=XYZ;Database=abc;Trusted_Connection=yes;")
HttpContext.Current.Response.AddHeader("content-disposition", attachment)
HttpContext.Current.Response.ContentType = "text/csv"
cnn.Open()
sql = GetReportSql(m_sBranch, m_sRegion)
Dim cmd As SqlCommand = New SqlCommand(sql, cnn)
Dim dr As SqlDataReader
dr = cmd.ExecuteReader()
HttpContext.Current.Response.Write("PTW JOBS - EXPORTED ON " + DateTime.Now)
For i = 0 To dr.FieldCount - 1
strLine = strLine & dr.GetName(i).ToString & ","
Next
HttpContext.Current.Response.Write(strLine)
Dim sb As StringBuilder = New StringBuilder()
Dim temp As String = ""
While dr.Read()
For i = 0 To dr.FieldCount - 1
temp = temp & dr.GetValue(i)
temp = temp.Replace(",", " ")
sb.Append(temp & ",")
temp = ""
Next
sb.AppendLine()
strLine = ""
End While
HttpContext.Current.Response.Write(sb.ToString())
End Sub
Any help will be highly appreciated. Thanks.
Look into the OpenXML SDK:
I understand that my example doesn't convert .csv files, but it will steer you in the right direction.
http://msdn.microsoft.com/en-us/library/bb448854(office.14).aspx
I've used it in asp.net to create xlsx documents on the fly, streamed directly to the web client:
public static System.IO.MemoryStream ConvertToExcel(DataSet ds)
{
System.IO.MemoryStream stream = new System.IO.MemoryStream();
using (SpreadsheetDocument package = SpreadsheetDocument.Create(stream, SpreadsheetDocumentType.Workbook, true))
{
package.AddWorkbookPart();
package.WorkbookPart.Workbook = new Workbook();
package.WorkbookPart.AddNewPart<WorksheetPart>();
if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
DataTable tbl = ds.Tables[0];
SheetData xlSheetData = new SheetData();
foreach (DataRow row in tbl.Rows)
{
Row xlRow = new Row();
foreach (DataColumn col in tbl.Columns)
{
object cellData = row[col];
Cell xlCell = null;
if (cellData != null)
{
xlCell = new Cell(new InlineString(new DocumentFormat.OpenXml.Spreadsheet.Text(cellData.ToString()))) { DataType = CellValues.InlineString };
}
else
{
xlCell = new Cell(new InlineString(new DocumentFormat.OpenXml.Spreadsheet.Text(String.Empty))) { DataType = CellValues.InlineString };
}
xlRow.Append(xlCell);
}
xlSheetData.Append(xlRow);
}
package.WorkbookPart.WorksheetParts.First().Worksheet = new Worksheet(xlSheetData);
package.WorkbookPart.WorksheetParts.First().Worksheet.Save();
// create the worksheet to workbook relation
package.WorkbookPart.Workbook.AppendChild(new Sheets());
package.WorkbookPart.Workbook.GetFirstChild<Sheets>().AppendChild(new Sheet()
{
Id = package.WorkbookPart.GetIdOfPart(package.WorkbookPart.WorksheetParts.First()),
SheetId = 1,
Name = "Sheet1"
});
package.WorkbookPart.Workbook.Save();
}
}
return stream;
}
Shariful, from what I've read (not tried yet), I believe the best method is to set your HTTP Response headers as outlined here.
In short, the key seems to be setting the content-disposition header to "attachment".
e.g.:
Content-Disposition: attachment; filename=<file name.ext>
Sorry that I haven't tested this, but in my searching for something closely related, almost every place I went suggests to use this method in order to force download dialog.
Related
I'm using Excel to create a form that is linked to another sheet that acts as a database.
This is my form (worksheet's name : "Form"):
And this is part of the database (worksheet's name: "Data"):
Right now it connects using a VBA script that is activated using the "save" button (green). Here's parts of the script:
Private Sub destBook()
setFormBook
If (destinationBook Is Nothing) Then
Dim file As String
file = ThisWorkbook.Sheets("_options").Cells(2, 26).Value //"path/to/the/database/file.xlsx"
If (IsEmpty(file)) Then
ThisWorkbook.Sheets("_options").Select
ThisWorkbook.Sheets("_options").Cells(2, 26).Select
Dim m As VbMsgBoxResult
m = MsgBox("")
Else
Set destinationBook = Workbooks.Open(file)
End If
End If
End Sub
Sub SaveClick()
Dim dataIdx As Integer
dataIdx = GetIdx()
If (dataIdx >= 2) Then
destBook
If (hasLock() = False) Then
WarnNoLock
closeDst
Else
Dim mappingRng As Range: Set mappingRng = ThisWorkbook.Sheets("_mappings").Range("F2:F71")
Dim rowIdx As Integer
For rowIdx = 1 To mappingRng.Rows.count
Dim FormRange As Range
Set FormRange = mappingRng.Cells(RowIndex:=rowIdx, ColumnIndex:=1)
If FormRange <> "" Then
Dim dataCol As Integer
Dim newValue As String
dataCol = mappingRng.Cells(RowIndex:=rowIdx, ColumnIndex:=2)
newValue = ThisWorkbook.Sheets("Form").Range(FormRange).Value
destinationBook.Sheets("Data").Cells(dataIdx, dataCol).Value = newValue
End If
Next
' refresh
Application.CalculateFull
End If
' close & save
closeDst
End If
End Sub
My question : Instead of saving/re-writing the data (Form) to another Excel file (Data), is it possible to save/re-write the data (Form) to a Google Sheet document ?
My guess would be to use the sharing link, but not sure how to make it works.
you can import JsonConverter.bas into your project (Open VBA Editor, Alt + F11; File > Import File) from https://github.com/VBA-tools/VBA-JSON/releases
and make table in your excel sheet, input this code to your module
Sub ConnectSheets()
Set xmlhttp = CreateObject("MSXML2.ServerXMLHTTP.6.0") 'To use POST http Request
'Get data table as JSON
tableData = JsonConverter.ConvertToJson(Sheets("Page1").ListObjects("Table1").Range.Value)
' 'Create All Json to Send
Data = "{""dataReq"": " & vbNewLine & tableData & vbNewLine & ", " & vbNewLine & " ""fname"":""pasteData""}"
Debug.Print Data
'Define the google URL
myurl = "https://script.google.com/macros/s/AKfycbzE0nm-Jz2yE4IWc7OB_ter8NrNKBL9SXuxi6cG74FeUpwCx6T9tFZyPd13dRxgaqEm/exec"
xmlhttp.Open "POST", myurl, False 'define method to use
xmlhttp.Send Data 'execute call
sGetResult = xmlhttp.ResponseText 'read response
Debug.Print sGetResult 'view response
End Sub
and put code to your google sheet, apply as webapp
function doPost(request = {}) {
const { parameter, postData: { contents, type } = {} } = request; //request data
const { dataReq = {} } = JSON.parse(contents); //content
const { fname = {} } = JSON.parse(contents); //function name
const response = {
status: "function not found: " + fname, // prepare response in function not found
data2: dataReq
}
switch (fname) { //function selection
case 'pasteData':
var output = JSON.stringify(pasteData(dataReq)) //call function with data, name and type from request
break
default:
var output = JSON.stringify(response)
break
}
return ContentService.createTextOutput(output).setMimeType(ContentService.MimeType.JSON); //response to frontend
}
function pasteData(dataReq) {
const id = '1wtGM5QL0LwIYJoU9joOO31n_kBbJJJHRFaKtIdwWOeU'; //id of Google Sheet
var sheet = SpreadsheetApp.openById(id).getSheetByName('Page1'); //sheet
sheet.clear(); //delete data
sheet.getRange(1, 1, dataReq.length, dataReq[0].length).setValues(dataReq); // paste new data
return "Numbers of sheets added: "+ dataReq.length; //return a response
}
I have a method which is use to extract excel by copying it to a response and downloading it to the browser. Everything checks out fine apart from the two formatting issues which are encountered.
1 . You see i have some values which are defined like '10-2', the problem is that excel is treating it like a date(which should not happen).
2 . All the Zeroes in the column are disappearing.
I presume changing the column to a text type might resolve the issue but i cant seem to figure out how to do it.
Would be a great help if someone can help me with this.
The code i am using is below:
Dim name As String = "SweepstakesReport_" & RewardCodeForName & "_" & DateTime.Now.ToString("yyyyMMdd")
Dim tmp As String = ""
Dim tmptime As String = ""
Dim ExcelFile As String = ""
Dim stwWriter As System.IO.StringWriter = New System.IO.StringWriter
Dim htwWriter As System.Web.UI.HtmlTextWriter = New System.Web.UI.HtmlTextWriter(stwWriter)
Dim dgGrid As DataGrid = New DataGrid
Dim ds As New DataSet
ds = Session("dsRedeemed")
dgGrid.DataSource = ds.Tables(0).DefaultView
dgGrid.HeaderStyle.Font.Bold = True
dgGrid.DataBind()
dgGrid.RenderControl(htwWriter)
ExcelFile = name & ".xls"
Response.Clear()
Response.AddHeader("content-disposition", String.Format("attachment; filename={0}", ExcelFile))
'Response.ContentType = "application/ms-excel"
Response.ContentType = "application/octet-stream"
'Response.ContentEncoding = System.Text.Encoding.Unicode
'Response.BinaryWrite(System.Text.Encoding.Unicode.GetPreamble())
'Response.ContentType = "application/octet-stream"
Response.Write(stwWriter.ToString)
Response.End()
Thanks,
Haris.
I had a code in MVC which successfully exports out the Excel file but how do I add the password into the Excel file?
My code:
public ActionResult Report(string id)
{
LocalReport lr = new LocalReport();
string path = Path.Combine(Server.MapPath("~/Report"), "ReportStateArea.rdlc");
if (System.IO.File.Exists(path))
{
lr.ReportPath = path;
}
else
{
return View("Index");
}
List<StateArea> cm = new List<StateArea>();
using (myDatabaseEntities dc = new myDatabaseEntities())
{
cm = dc.StateAreas.ToList();
}
ReportDataSource rd = new ReportDataSource("MyDataset", cm);
lr.DataSources.Add(rd);
string reportType = id ;
string mimeType;
string encoding;
string fileNameExtension;
string deviceInfo =
"<DeviceInfo>" +
" <OutputFormat>" + id + "</OutputFormat>" +
" <PageWidth>8.5in</PageWidth>" +
" <PageHeight>11in</PageHeight>" +
" <MarginTop>0.5in</MarginTop>" +
" <MarginLeft>1in</MarginLeft>" +
" <MarginRight>1in</MarginRight>" +
" <MarginBottom>0.5in</MarginBottom>" +
"</DeviceInfo>";
Warning[] warnings;
string[] streams;
byte[] renderedBytes;
renderedBytes = lr.Render(
reportType,
deviceInfo,
out mimeType,
out encoding,
out fileNameExtension,
out streams,
out warnings);
return File(renderedBytes, mimeType);
}
You can use FileStream Class to write renderedBytes on a file.
Dim strExcelFile As String = "C:\YourPathTo\ExcelFile.xls"
Dim fs As New FileStream(strExcelFile, FileMode.Create)
fs.Write(renderedBytes, 0, renderedBytes.Length)
fs.Close()
fs.Dispose()
Then use Microsoft.Office.Interop.Excel.dll to add a password to an existing workbook:
Dim appExcel As Excel.Application
Dim wbExcel As Excel.Workbook
appExcel = New Excel.Application
wbExcel = appExcel.Workbooks.Open(strExcelFile)
wbExcel.Password = "YourPassword"
appExcel.DisplayAlerts = False
wbExcel.SaveAs(strExcelFile)
appExcel.DisplayAlerts = True
wbExcel.Close()
I used DisplayAlerts to suppress prompts and alert messages while using SaveAs to overwrite existing file; when a message requires a response, Microsoft Excel chooses the default response.
My code is in VB.NET but you can simply translate it in C#.
I have created a windows application using list.asmx (getlistitems method) to download documents from a document library which is on another server. I am able to access document names, url, etc. When I use following code to download a file, it is returning html of the login page as content of each file that I am trying to download.
Any thoughts?
Dim spAuthentication As New Authentication()
spAuthentication.Url = authenticationWSAddress
spAuthentication.CookieContainer = New CookieContainer()
Dim spLists As New Lists()
spLists.Url = listWSAddress
'Try to login to SharePoint site with Form based authentication
Dim loginResult As LoginResult = spAuthentication.Login(userName, password)
Dim cookie As New Cookie()
'If login is successfull
If loginResult.ErrorCode = LoginErrorCode.NoError Then
'Get the cookie collection from the authenticatin web service
Dim cookies As CookieCollection = spAuthentication.CookieContainer.GetCookies(New Uri(spAuthentication.Url))
'Get the specific cookie which contains the security token
cookie = cookies(loginResult.CookieName)
'Initialize the cookie container of the list web service
spLists.CookieContainer = New CookieContainer()
'set the cookie of list web service to the authenticatio cookie
spLists.CookieContainer.Add(cookie)
'Dim responseNode As XmlNode = spLists.GetListCollection()
'response = responseNode.InnerXml
Dim query As String = "<mylistitems><Query><Where><Eq><FieldRef Name='FileDirRef' /><Value Type='Url'>DocLib/Property Documents/BELASERA AT FULTON (lax10027)/Master Meter Invoices</Value></Eq></Where></Query><QueryOptions><ViewAttributes Scope='RecursiveAll' IncludeRootFolder='False' /><IncludeAttachmentUrls>TRUE</IncludeAttachmentUrls><ViewFields><FieldRef Name='EncodedAbsUrl'/></ViewFields></QueryOptions></mylistitems>"
Dim doc As New XmlDocument()
doc.LoadXml(query)
Dim dt As DataTable = Nothing
Dim queryNode As XmlNode = doc.SelectSingleNode("//Query")
Dim viewNode As XmlNode = doc.SelectSingleNode("//ViewFields")
Dim optionNode As XmlNode = doc.SelectSingleNode("//QueryOptions")
Dim retNode As XmlNode = spLists.GetListItems("DocLib", String.Empty, queryNode, viewNode, String.Empty, optionNode, Nothing)
Dim ds As New DataSet()
Using sr As New StringReader(retNode.OuterXml)
ds.ReadXml(sr)
End Using
If ds.Tables("Row") IsNot Nothing AndAlso ds.Tables("Row").Rows.Count > 0 Then
dt = ds.Tables("Row").Copy()
For Each myrow As DataRow In dt.Rows
' myrow.Item(0) contains url of the document
If myrow.Item(0) IsNot Nothing AndAlso myrow.Item(0) <> "" Then
DownLoadAttachmentold(myrow.Item("ows_EncodedAbsUrl"), RemoveLookupID(myrow.Item("ows_FileLeafRef")))
End If
Next
End If
Public Shared Sub DownLoadAttachment(ByVal strURL As String, ByVal strFileName As String)
Dim myWebClient As New WebClient()
Dim DestinationFolder As String = "C:\\DownLoads\\"
Form2.RTBStatus.AppendText("Downloading File " + strFileName + " from " + strURL + " .......")
' The DownloadFile() method downloads the Web resource and saves it into the current file-system folder.
myWebClient.DownloadFile(strURL, DestinationFolder + strFileName)
'Form2.RTBStatus.AppendText("Successfully Downloaded file ""{0}"" from ""{1}""", "C:\\DownLoads\\" + strFileName, strURL)
Form2.RTBStatus.AppendText((ControlChars.Cr + "Downloaded file saved in the following file system folder:" + ControlChars.Cr + ControlChars.Tab + DestinationFolder))
End Sub
DownloadAttachment also needs to make (forms-based) authenticated HTTP requests.
An example in C# below:
request = (HttpWebRequest)WebRequest.Create(strURL);
request.Credentials = System.Net.CredentialCache.DefaultCredentials;//adapt for your FBA
request.AllowWriteStreamBuffering = false;
response = (HttpWebResponse)request.GetResponse();
Stream s = response.GetResponseStream();
FileStream fs = new FileStream(#"C:\DownLoads\"+strFileName, FileMode.Create);
We have an ASP.NET 1.1 application that uses Crystal Reports to spit out an excel spreadsheet. The codes works under IIS6 but when we try to migrate it to IIS7 it is spitting out html with no content instead of the Excel file.
The MIME Type exists. Below is the code we are using. I did not write this code as I'm working primarily in 3.5 framework now. My assumption is I am missing something in the IIS7 configuration not the code since it works on IIS6. The rest of the ASP.NET 1.1 application works on IIS7.
Dim cr As ReportClass
'EXPORT the report based on the export type passed in.
Dim ExpOptions As New ExportOptions
Dim ContentType As String
Dim strExt As String
Trace.Write("DisplayReport reportname=" + ReportName + " SQL=" + SQL + " SQLSub1=" + Convert.ToString(Session("SQLSub1")))
'Get the report filled with the data.
If Session("SQLSub1") <> "" Then
If Not Session("SubRptName") Is Nothing Then
cr = PopulateReport(GetReportObject(ReportName), SQL, Session("SQLSub1"), Session("SubRptName"))
Session("SQLSub1") = ""
Session("SubRptName") = Nothing
Else
cr = PopulateReport(GetReportObject(ReportName), SQL, Session("SQLSub1"))
Session("SQLSub1") = ""
End If
Else
cr = PopulateReport(GetReportObject(ReportName), SQL)
End If
If DisplayType = ReportType.Excel Then
If ReportName.ToUpper = "ACTION" Or ReportName.ToUpper = "INVENTORY_EXCEL" _
Or ReportName.ToUpper = "UNDERPERFORM" Or ReportName.ToUpper = "EMPLOYEE_EXCEL" Then
Dim excelFormatOpts As New ExcelFormatOptions
' Set the excel format options.
excelFormatOpts.ExcelTabHasColumnHeadings = True
excelFormatOpts.ExcelUseConstantColumnWidth = False
ExpOptions.FormatOptions = excelFormatOpts
Else
ExpOptions.FormatOptions = New ExcelFormatOptions
End If
ExpOptions.ExportFormatType = ExportFormatType.Excel
ContentType = "application/vnd.ms-excel"
strExt = ".xls"
ElseIf DisplayType = ReportType.PDF Then
ExpOptions.ExportFormatType = ExportFormatType.PortableDocFormat
ExpOptions.FormatOptions = New PdfRtfWordFormatOptions
ContentType = "application/pdf"
strExt = ".pdf"
End If
'Stream the report to the screen
Dim req As New ExportRequestContext
req.ExportInfo = ExpOptions
Dim s As Stream
Try
s = cr.FormatEngine.ExportToStream(req)
Catch ex As Exception
Trace.Warn("DisplayReport cr.FormatEngine.ExportToStream(req) failed: " + ex.Message)
Dim x As String = String.Empty
End Try
Response.Clear()
'Response.ClearHeaders()
'Response.ClearContent()
Response.Buffer = True
Response.ContentType = ContentType
Response.AddHeader("Content-Type", ContentType)
Dim buffer(s.Length) As Byte
s.Read(buffer, 0, Int(s.Length))
Response.BinaryWrite(buffer)
Dim strContentDisposition As String = "inline;filename=" & ReportName.ToString.ToLower & strExt.ToString
Trace.Write("DisplayReport strContentDisposition=" + strContentDisposition)
Response.AddHeader("Content-Disposition", strContentDisposition)
Response.Cache.SetMaxAge(New TimeSpan(0, 0, 10))
Response.End()
Asked some devs here at work, this is what I got so far:
"Never seen that before, I’ve never even used the export to stream option in crystal before. However, if I were to guess, I would look at server permissions as a possible fault. I’ve seen situations where the user has to have special privileges to access streams."