VB .NET server generating Excel file on the fly - html

I have a VB .NET web application running on a server with multiple requests and performance requirements.
I have a function that retrieves some data from a DB and has to generate an excel report to show to the system users.
I somehow did it, but my solution has not the performance I'd like it to have: basically what my code does is:
The server accepts the request of report generating
The server fills an excel file
The server saves locally the xls file
The server attaches the file to the html response and the user downloads it
The server deletes the file (when? I need to handle borderline cases too)
The code snippet is like:
Public Sub ExportaDataTableToExcel(ByVal dt As System.Data.DataTable, ByVal Page As System.Web.UI.Page, ByVal ReportName As String)
Dim oExcel As Excel.Application
Dim oBook As Excel.Workbook
Dim oSheet As Excel.Worksheet
Dim colIndex As Integer
Dim rowIndex As Integer
oExcel = New Excel.Application
oBook = oExcel.Workbooks.Add(Type.Missing)
oSheet = oBook.Worksheets(1)
'Export the Columns to excel file
For Each dc In dt.Columns
colIndex = colIndex + 1
oSheet.Cells(1, colIndex) = dc.ColumnName
Next
oBook.SaveAs("C:\file.xls")
oSheet = Nothing
oBook.Close()
Page.Response.AddHeader("content-disposition", "attachment;filename=" & ReportName & ".xls")
Page.Response.Charset = String.Empty
Page.Response.ContentType = "vnd.application/ms-excel"
Page.Response.TransmitFile("C:\file.xls")
Page.Response.Flush()
Page.Response.End()
oExcel.Quit()
End Sub
As you can see the server generates the xls file locally in C:\file.xls, then trasmittes the file in the response page.
What I'd like to do, and I really don't know if it's possible as I did not found any example on this, is generating the xls file on the fly without saving it locally (maybe returning as a Stream of bytes or something like this) and then assembling this as xls file in the response page, without saving the file locally.
I tried using both Page and System.IO.StringWriter with no luck, maybe I'm doing something wrong.
The following code acts abnormally, asking me to save modifies on the file (on the server side), and downloading an xls file that has parts of the html of the page, generating errors about missing css files and displaying part of the page. So, with this approach I'm almost at zero. Here it is the code:
Public Sub ExportaDataTableToExcel(ByVal dt As System.Data.DataTable, ByVal Page As System.Web.UI.Page, ByVal ReportName As String)
Dim oExcel As Excel.Application
Dim oBook As Excel.Workbook
Dim oSheet As Excel.Worksheet
Dim colIndex As Integer
Dim rowIndex As Integer
oExcel = New Excel.Application
oBook = oExcel.Workbooks.Add(Type.Missing)
oSheet = oBook.Worksheets(1)
'Export the Columns to excel file
For Each dc In dt.Columns
colIndex = colIndex + 1
oSheet.Cells(1, colIndex) = dc.ColumnName
Next
oSheet = Nothing
oBook.Close()
Dim stringWrite As System.IO.StringWriter = New System.IO.StringWriter
Dim htmlWrite As System.Web.UI.Html32TextWriter = New System.Web.UI.Html32TextWriter(stringWrite)
Page.Response.Clear()
Page.Response.AddHeader("content-disposition", "attachment;filename=" & ReportName & ".xls")
Page.Response.Charset = String.Empty
Page.Response.ContentType = "vnd.application/ms-excel"
Page.Response.WriteFile(stringWrite.ToString)
Page.Response.Flush()
Page.Response.End()
oExcel.Quit()
End Sub

I know I can help with at least one of those problems you are having, Lateralus. Ive taken a snippet from our live server here to show you.
Edit: This one transmits a CSV file and we had the problem initially with the HTML showing up in the file. We opted to not use excel in this particular instance but, the problems are likely one in the same.
I believe that you need to add an additional header to your page response in order to remove the HTML that you are getting in the file.
Here is an example. As a warning, I'm not entirely sure how secure this method is. We use this within our network so it didn't need to be as locked down.
Dim LiveFileStream As FileStream = New FileStream("C:\inetpub\wwwroot\" &_
"Website\CSVFile.csv", FileMode.Open, FileAccess.Read)
Dim fileBuffer(CInt(LiveFileStream.Length)) As Byte
LiveFileStream.Read(fileBuffer, 0, CInt(LiveFileStream.Length))
LiveFileStream.Close()
Response.Clear()
Response.Charset = "utf-8"
Response.ContentType = "text/plain"
'I believe if you are to add the following header
'it will fix the problem with HTML showing in document
Response.AddHeader("Content-Length", fileBuffer.Length.ToString)
Response.AddHeader("Content-Disposition", "attachment; filename=CSVFile.csv")
Response.BinaryWrite(fileBuffer)
Response.End()

Related

Convert RTF embedded OLE to HTML in Access in VBA

I've got a table that has an embedded OLE field that contains RichText formatted data. I need to transfer this data to MySQL database and convert it to HTML. I use Access. Is there a way to do it quickly in VBA?
I searched the web, most people use RichText control (richtx32.ocx) to get plain text, but I need it to remain formatted and I also don't have this control.
Here is how I solved my problem:
Option Explicit
Public wrd As Word.Application
Public doc As Word.Document
Function RTF2HTMLviaWord(rtf As String) As String
'Open Tools --> References --> and check Microsoft Scripting Runtime
Dim fso As New FileSystemObject
Dim text As TextStream
Dim temp As String
temp = Environ("TEMP")
If Len(rtf) > 1 Then
Set text = fso.CreateTextFile(temp & "\RTF2HTML.rtf", True)
text.Write rtf
text.Close
If wrd Is Nothing Then
Set wrd = New Word.Application
End If
Set doc = wrd.Documents.Open(temp & "\RTF2HTML.rtf", False)
doc.SaveAs temp & "\RTF2HTML.htm", wdFormatHTML
doc.Close
fso.DeleteFile temp & "\RTF2HTML.rtf"
Set text = fso.OpenTextFile(temp & "\RTF2HTML.htm", ForReading, False)
RTF2HTMLviaWord = text.ReadAll
text.Close
fso.DeleteFile temp & "\RTF2HTML.htm"
Else
RTF2HTMLviaWord = ""
End If
End Function
The only downside is that Word produces too many garbage HTML tags. I wish it could save minimal HTML tags without formatting.

Import info from Word 2013 form into Access 2013 via VBA

I’m trying to make VBA script for Access 2013 which will help to process Word 2013 forms from folder, attach these files of Word 2013 form to relevant record entry and attach pdf file from same folder with the same name.
Since I’m not a programmer each try leads me to next error.
Can anyone help to make it work.
Thanks.
This code does task of collecting data from files .docx in folder.
Then not to keep files in folder I would like to save them in DB by the proper record.
How to add code that will attach pdf and docx file to the relevant record, assuming that filename of docx and pdf is the same?
I need a clue how to incert it to relevant record or start new part of script. what commands can be used and in what place to start new part of script?
Private Sub ImportFormdata_Click()
Dim appWord As Word.Application
Dim doc As Word.Document
Dim SourceFolderPath As String
Dim FormFile As String
Dim strName As String
Dim rst As DAO.Recordset
SourceFolderPath = CurrentProject.Path & "\"
FormFile = Dir(SourceFolderPath & "*.docx", vbNormal)
Do While FormFile <> ""
Set appWord = CreateObject("Word.Application")
strName = SourceFolderPath & FormFile
Set doc = appWord.Documents.Open(strName)
appWord.Visible = False
Set rst = CurrentDb.OpenRecordset("FormData")
With rst
.AddNew
![Question1] = doc.FormFields("Q1").result
![Question2] = doc.FormFields("Q2").result
![Question3] = doc.FormFields("Q3").result
![File name] = FormFile
.Update
.Close
End With
doc.Close
appWord.Quit
FormFile = Dir
Loop
MsgBox "Forms imported!"
End Sub

Export all tables to txt files with export specification

I have a Access DB containing several different tables, each with a different structure (number & names of fields, number of rows, title).
What I would like to do is to export all these tables into txt files, with a given separator ("|"), point as decimal separator, quotes for strings.
I have browsed the internet and what I got was:
use DoCmd.TransferText acExportDelim command
save a customized export specification and apply it
I get an error messagge ("object does not exist") and I think it is related to the fact that the export specification is "sheet-specific", i.e. does not apply to tables with different fields and fieldnames.
Can you help me?
thanks!!
EDIT.
I post also the original code I run. As I said before, I am new to VBA, so I just looked for a code on the web, adapted it to my needs, and run.
Public Sub ExportDatabaseObjects()
On Error GoTo Err_ExportDatabaseObjects
Dim db As Database
Dim db As DAO.Database
Dim td As TableDef
Dim sExportLocation As String
Dim a As Long
Set db = CurrentDb()
sExportLocation = "C:\" 'Do not forget the closing back slash! ie: C:\Temp\
For a = 0 To db.TableDefs.Count - 1
If Not (db.TableDefs(a).Name Like "MSys*") Then
DoCmd.TransferText acExportDelim, "Export_specs", db.TableDefs(a).Name, sExportLocation & db.TableDefs(a).Name & ".txt", True
End If
Next a
Set db = Nothing
MsgBox "All database objects have been exported as a text file to " & sExportLocation, vbInformation
Exit_ExportDatabaseObjects:
Exit Sub
Err_ExportDatabaseObjects:
MsgBox Err.Number & " - " & Err.Description
Resume Exit_ExportDatabaseObjects
End Sub
Before running the code, I manually exported the first table saving the Export_specs to a file.
Consider a db with two tables, A and B.
When I run the code A is properly exported, then I get the following errore message "3011 - The Microsoft Access database engine could not find the object 'B#txt'. Make sure the object exists and that you spell its name and the path name correctly. If 'B#txt' is not a local object, check your network connection or contact the server administration".
So, it's kind of complex. I've created a routine that imports files using ImportExport Specs, you should be able to easily adapt to your purpose. The basic operation is to create a spec that does exactly what you want to one file. Then, export this spec using this code:
Public Function SaveSpecAsXMltoTempDirectory(sSpecName As String)
Dim oFSO As FileSystemObject
Dim oTS As TextStream
Set oFSO = New FileSystemObject
Set oTS = oFSO.CreateTextFile("C:\Temp\" & sSpecName & ".xml", True)
oTS.Write CurrentProject.ImportExportSpecifications(sSpecName).XML
oTS.Close
Set oTS = Nothing
Set oFSO = Nothing
End Function
Then open this file in Notepad and replace the file name with some placeholder (I used "FILE_PATH_AND_NAME" in this sample). Then, import back into database using this code:
Public Function SaveSpecFromXMLinTempDirectory(sSpecName As String)
Dim oFSO As FileSystemObject
Dim oTS As TextStream
Dim sSpecXML As String
Dim oSpec As ImportExportSpecification
Set oFSO = New FileSystemObject
Set oTS = oFSO.OpenTextFile("C:\Temp\" & sSpecName & ".xml", ForReading)
sSpecXML = oTS.ReadAll
For Each oSpec In CurrentProject.ImportExportSpecifications
If oSpec.Name = sSpecName Then oSpec.Delete
Next oSpec
Set oSpec = CurrentProject.ImportExportSpecifications.Add(sSpecName, sSpecXML)
Set oSpec = Nothing
oTS.Close
Set oTS = Nothing
Set oFSO = Nothing
End Function
Now you can cycle thru the files and replace the placeholder in the spec with the filename then execute it using this code:
Public Function ImportFileUsingSpecification(sSpecName As String, sFile As String) As Boolean
Dim oSpec As ImportExportSpecification
Dim sSpecXML As String
Dim bReturn As Boolean
'initialize return variable as bad until function completes
bReturn = False
'export data using saved Spec
' first make sure no temp spec left by accident
For Each oSpec In CurrentProject.ImportExportSpecifications
If oSpec.Name = "Temp" Then oSpec.Delete
Next oSpec
sSpecXML = CurrentProject.ImportExportSpecifications(sSpecName).XML
If Not Len(sSpecXML) = 0 Then
sSpecXML = Replace(sSpecXML, "FILE_PATH_AND_NAME", sFile)
'now create temp spec to use, get template text and replace file path and name
Set oSpec = CurrentProject.ImportExportSpecifications.Add("Temp", sSpecXML)
oSpec.Execute
bReturn = True
Else
MsgBox "Could not locate correct specification to import that file!", vbCritical, "NOTIFY ADMIN"
GoTo ExitImport
End If
ExitImport:
On Error Resume Next
ImportFileUsingSpecification = bReturn
Set oSpec = Nothing
Exit Function
End Function
Obviously you'll need to find the table name in the spec XML and use a placeholder on it as well. Let me know if you can't get it to work and i'll update for export.

How to copy the contents of an attached file from an MS Access DB into a VBA variable?

Background Information:
I am not very savvy with VBA, or Access for that matter, but I have a VBA script that creates a file (a KML to be specific, but this won't matter much for my question) on the users computer and writes to it using variables that link to records in the database. As such:
Dim MyDB As Database
Dim MyRS As Recordset
Dim QryOrTblDef As String
Dim TestFile As Integer
QryOrTblDef = "Table1"
Set MyDB = CurrentDb
Set MyRS = MyDB.OpenRecordset(QryOrTblDef)
TestFile = FreeFile
Open "C:\Testing.txt"
Print #TestFile, "Generic Stuff"
Print #TestFile, MyRS.Fields(0)
etc.
My Situation:
I have a very large string(a text document with a large list of polygon vertex coordinates) that I want to add to a variable to be printed to another file (a KML file, noted in the above example). I was hoping to add this text file containing coordinates as an attachment datatype to the Access database and copy its contents into a variable to be used in the above script.
My Question:
Is there a way I can access and copy the data from an attached text file (attached as an attachment data type within a field of an MS Access database) into a variable so that I can use it in a VBA script?
What I have found:
I am having trouble finidng information on this topic I think mainly because I do not have the knowledge of what keywords to be searching for, but I was able to find someones code on a forum, "ozgrid", that seems to be close to what I want to do. Though it is just pulling from a text file on disk rather than one attached to the database.
Code from above mentioned forum that creates a function to access data in a text file:
Sub Test()
Dim strText As String
strText = GetFileContent("C:\temp\x.txt")
MsgBox strText
End Sub
Function GetFileContent(Name As String) As String
Dim intUnit As Integer
On Error Goto ErrGetFileContent
intUnit = FreeFile
Open Name For Input As intUnit
GetFileContent = Input(LOF(intUnit), intUnit)
ErrGetFileContent:
Close intUnit
Exit Function
End Function
Any help here is appreciated. Thanks.
I am a little puzzled as to why a memo data type does not suit if you are storing pure text, or even a table for organized text. That being said, one way is to output to disk and read into a string.
''Ref: Windows Script Host Object Model
Dim fs As New FileSystemObject
Dim ts As TextStream
Dim rs As DAO.Recordset, rsA As DAO.Recordset
Dim sFilePath As String
Dim sFileText As String
sFilePath = "z:\docs\"
Set rs = CurrentDb.OpenRecordset("maintable")
Set rsA = rs.Fields("aAttachment").Value
''File exists
If Not fs.FileExists(sFilePath & rsA.Fields("FileName").Value) Then
''It will save with the existing FileName, but you can assign a new name
rsA.Fields("FileData").SaveToFile sFilePath
End If
Set ts = fs.OpenTextFile(sFilePath _
& rsA.Fields("FileName").Value, ForReading)
sFileText = ts.ReadAll
See also: http://msdn.microsoft.com/en-us/library/office/ff835669.aspx

"User-defined type not defined" for Excel Range Using Late Binding In Access 2003

I am trying to write a VBA script which imports all of the Excel files in a folder into a table in Access 2003, first checking if they have been imported or not. That part is fine. The issue I run into is clearing out some of the formulas that don't get used on the spreadsheet which causes difficulty when Access tries to import the range. when running the code as-is, I get an error "User-defined type not defined".
I am using late binding since I am developing for a site that uses multiple versions of Office and therfore can't reference the same library using early binding. The problem code is below:
Private Sub Command2_Click()
'Declare Variables
Dim xlApp As Object
Dim xlBook As Object
Dim LSQL As String
Dim SkippedCounter As Integer
Dim ImportedCounter As Integer
Dim BUN As Long
Dim SubmitDate As Date
Dim LSQL2 As String
Dim LSQL3 As String
'Start counters for final notice
SkippedCounter = 0
ImportedCounter = 0
Dim myDir As String, fn As String
'Set directory for importing files
myDir = "U:\Five Star\Operations\restore\Surveys\My InnerView - 2010\Action plans\Action plans - input for DB\"
'Function for selecting files in folder
fn = Dir(myDir & "*.xls")
'Determine if there are files in side the folder
If fn = "" Then
MsgBox "Folder is Empty!"
Else
'Begin cycling through files in the folder
Do While fn <> ""
'Create new Excel Object
Set xlApp = CreateObject("Excel.Application")
'Make it appear on the screen while importing
xlApp.Visible = True
'Open the workbook at hand
Set xlBook = xlApp.Workbooks.Open(myDir & fn)
'Check to see if it has been imported already
If xlBook.Sheets("Action plan form").Range("A1").Value = "Imported" Then
'If it has been imported, add 1 to the counter, close the file and close the instance of Excel
SkippedCounter = SkippedCounter + 1
xlBook.Close
xlApp.Quit
Set xlBook = Nothing
Set xlApp = Nothing
Else
'Otherwise, unprotect the worksheet
xlBook.UnProtect Password:="2010"
Dim c As Range
'Unhide worksheet needed and clean it up
xlBook.Sheets("Action plan DB data").Visible = True
xlBook.Sheets("Action plan DB data").Range("B10:O10").ClearFormats
xlBook.Sheets("Action plan DB data").Range("N11:N84").ClearFormats
For Each c In xlBook.Sheets("Action plan DB data").Range("DB_import")
If c.Value = "" Or c.Value = 0 Then c.Clear
Next c
...
The rest of the code should run fine, it jsut has an issue with the declaration of "range" and looping through it. Thanks for your help!
Remove As Range from Dim c As Range and that will make c into an object. That way when it gets late-bound to a range you won't have any issues.