Read POSTed Binary File And Write To a New Binary File - excel

I'm creating a web page that will allow user to upload files to the server.
I was able to save the file on the server, but I notice that the office files (e.g. word, excel) are corrupted and can not be opened.
My UI is fairly simple
<form method="post" enctype="multipart/form-data" action="uploadFile.asp">
<p>Select a file:<br><input type=File size=30 name="file1"></p>
<input type=submit value="Upload">
</form>
In my uploadFile.asp, I'm using VBScript. I tried to read and write the binary data and write it directly.
Function SaveBinaryData(FileName, ByteArray)
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
'Create Stream object
Dim BinaryStream
Set BinaryStream = CreateObject("ADODB.Stream")
'Specify stream type - we want To save binary data.
BinaryStream.Type = adTypeBinary
'Open the stream And write binary data To the object
BinaryStream.Open
BinaryStream.Write ByteArray
'Save binary data To disk
BinaryStream.SaveToFile FileName, adSaveCreateOverWrite
End Function
Dim biData
biData = Request.BinaryRead(Request.TotalBytes)
SaveBinaryData "C:\Uploads\ww.xlsx", biData
Like I mentioned previously, if I upload a excel or word file, the file is corrupted. However, text files will work just fine.
I tried other solutions I found online such as Pure ASP, ShadowUploader, etc, but couldn't find one that work properly, they all result in corrupt file or doesn't upload at all.
How can I get it to work properly so that I can upload binary files such as microsft word or excel?
Any help is appreciated!

the form
<form method="post" action="post.asp" enctype="multipart/form-data">
<input type='file' name='blob' size='80' />
</form>
Then the code of post.asp. First of all asp binary code:
Dim folder
folder = "public"
Response.Expires=0
Response.Buffer = TRUE
Response.Clear
Sub BuildUploadRequest(RequestBin)
PosBeg = 1
PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(13)))
boundary = MidB(RequestBin,PosBeg,PosEnd-PosBeg)
boundaryPos = InstrB(1,RequestBin,boundary)
Do until (boundaryPos=InstrB(RequestBin,boundary & getByteString("--")))
Dim UploadControl
Set UploadControl = CreateObject("Scripting.Dictionary")
'Get an object name
Pos = InstrB(BoundaryPos,RequestBin,getByteString("Content-Disposition"))
Pos = InstrB(Pos,RequestBin,getByteString("name="))
PosBeg = Pos+6
PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(34)))
Name = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))
PosFile = InstrB(BoundaryPos,RequestBin,getByteString("filename="))
PosBound = InstrB(PosEnd,RequestBin,boundary)
If PosFile<>0 AND (PosFile<PosBound) Then
PosBeg = PosFile + 10
PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(34)))
FileName = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))
nomefile=filename
UploadControl.Add "FileName", FileName
Pos = InstrB(PosEnd,RequestBin,getByteString("Content-Type:"))
PosBeg = Pos+14
PosEnd = InstrB(PosBeg,RequestBin,getByteString(chr(13)))
ContentType = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))
UploadControl.Add "ContentType",ContentType
PosBeg = PosEnd+4
PosEnd = InstrB(PosBeg,RequestBin,boundary)-2
Value = MidB(RequestBin,PosBeg,PosEnd-PosBeg)
Else
Pos = InstrB(Pos,RequestBin,getByteString(chr(13)))
PosBeg = Pos+4
PosEnd = InstrB(PosBeg,RequestBin,boundary)-2
Value = getString(MidB(RequestBin,PosBeg,PosEnd-PosBeg))
End If
UploadControl.Add "Value" , Value
UploadRequest.Add name, UploadControl
BoundaryPos=InstrB(BoundaryPos+LenB(boundary),RequestBin,boundary)
Loop
End Sub
Function getByteString(StringStr)
For i = 1 to Len(StringStr)
char = Mid(StringStr,i,1)
getByteString = getByteString & chrB(AscB(char))
Next
End Function
Function getString(StringBin)
getString =""
For intCount = 1 to LenB(StringBin)
getString = getString & chr(AscB(MidB(StringBin,intCount,1)))
Next
End Function
byteCount = Request.TotalBytes
RequestBin = Request.BinaryRead(byteCount)
Dim UploadRequest
Set UploadRequest = CreateObject("Scripting.Dictionary")
BuildUploadRequest RequestBin
Then the code to request.item from form
blob = UploadRequest.Item("blob").Item("Value")
Finally the code to save the file in server. I rename the name's file for not duplicating name and I create an univoque name with the mix of date and time.
contentType = UploadRequest.Item("blob").Item("ContentType")
filepathname = UploadRequest.Item("blob").Item("FileName")
filename = Right(filepathname,Len(filepathname)-InstrRev(filepathname,"\"))
value = UploadRequest.Item("blob").Item("Value")
Set ScriptObject = Server.CreateObject("Scripting.FileSystemObject")
arrayFile = split(filename,".")
estensioneFile = arrayFile(UBound(ArrayFile))
namefileuploaded = day(date())& month(date()) & year(date())& hour(time())&minute(time())& second(time())&"a."&estensioneFile
Set MyFile = ScriptObject.CreateTextFile(Server.mappath(folder)&"\"& namefileuploaded)
For i = 1 to LenB(value)
MyFile.Write chr(AscB(MidB(value,i,1)))
Next
MyFile.Close

I don't see how your code would work.
Classic ASP has no way accessing uploaded files like ASP.NET (Request.UploadedFiles) so if you don't use a a COM component then you need to read Request.BinaryStream and parse out the contents, which isn't so easy.
There are several Classic ASP scripts that do this and I would suggest you use one of these. I have used several and haven't had any problems. I suggest you try one of the free ones like: http://freevbcode.com/ShowCode.asp?ID=4596

Related

How to export text from annotation fields in Nuance Power PDF to Excel using VBA?

I am trying to export some text from annotation fields in Nuance Power PDF to Excel using VBA. I added the Nuance Power PDF reference to Excel VBA (PDF Plus).
I used it and it works well but the text returned from fields is empty.
Set PDFApp = CreateObject("NuancePDF.App")
Set dvDoc = CreateObject("NuancePDF.DVDoc")
dvDoc.Open("\\adpdc-2\Users$\a.goudinoux\Documents\Macro Formulaire\fiche.pdf")
Set ddDoc = dvDoc.GetDDDoc()
Set ddPage = ddDoc.AcquirePage(0)
nbannots = ddPage.GetNumAnnots() - 1
For i = 0 To nbannots
Texte = ""
Set ddAnnot = ddPage.GetAnnot(i)
Set ddText = ddDoc.CreateTextSelect(0, ddAnnot.GetRect())
ThisWorkbook.Sheets(1).Cells(1, i) = ddAnnot.GetTitle()
For k = 0 To ddText.GetNumText()
Texte = Texte & ddText.GetText(k)
Next
ThisWorkbook.Sheets(1).Cells(2, i) = Texte
Next
Part of the PDF document :
Results :
As you can see the first line is working but not the second one.
I thought the problem was with ddText but ddText.GetNumText() gives the right number of text elements in the text selection (ex : 2, 5, 4, etc...) when I run my program in Debug Mode.
I think the problem is from the function GetText(k).
I made it work once but I can't find my code back..
Do you see any mistake ?
Either your annotations are more complex than indicated or you're overthinking it.
Just read the annotation with GetContents and call it a day.
Set PDFApp = CreateObject("NuancePDF.App")
Set dvDoc = CreateObject("NuancePDF.DVDoc")
dvDoc.Open("\\adpdc-2\Users$\a.goudinoux\Documents\Macro Formulaire\fiche.pdf")
Set ddDoc = dvDoc.GetDDDoc()
Set ddPage = ddDoc.AcquirePage(0)
nbannots = ddPage.GetNumAnnots() - 1
For i = 0 To nbannots
Set ddAnnot = ddPage.GetAnnot(i)
ThisWorkbook.Sheets(1).Cells(1, i) = ddAnnot.GetTitle
ThisWorkbook.Sheets(1).Cells(2, i) = ddAnnot.GetContents
Next i

Download xls file to client from Datatable

I am developing a website on VisualStudio using VB. In one section of my site I make a DataBase Query, store the result in a DataTable and display it. I give the user the option of dowloading the information, what I would like to do is to download an XLS file to the client's side with the information in the datatable without creating the xls on the server side.
I currently have the following code section to send the file to the user
Dim fileToDownload = Server.MapPath("~/docs/QuejometroVF.pdf")
Response.ContentType = "application/octet-stream"
Dim cd = New ContentDisposition()
cd.Inline = False
cd.FileName = Path.GetFileName(fileToDownload)
Response.AppendHeader("Content-Disposition", cd.ToString())
Dim fileData = System.IO.File.ReadAllBytes(fileToDownload)
Response.OutputStream.Write(fileData, 0, fileData.Length)
But it requires a path to a local file in order to send it.
First I would like to know how to create a xls file from the datatable (only in memory) and then send that object as a file to the client's computer. If it is not possible, Could you tell me how to write the xls file in my server so I can then send it using the code above? I have not really figured out how to do it yet.
I was thinking on doint it that way because I don't want to keep files in the server when I already have that information on the database and I don't pretend on keeping that file stored.
Thank you
I export data to xls file using the following code, my backend is an Oracle database and that's where I get the data:
Dim MyConnection As OracleConnection = OpenConnection(Session("USERNAME"), Session("PASSWORD"))
Dim MyDataSet As New DataSet
MyDataSet = GetExportData(MyConnection, Session("UserDataKey"), Session("CompoundKey"), Session("LastOfCompoundKey"))
'I rename the dataset's table columns to what I want in the xls file
MyDataSet.Tables!data.Columns(0).ColumnName = "IDNumber"
MyDataSet.Tables!data.Columns(1).ColumnName = "FirstName"
MyDataSet.Tables!data.Columns(2).ColumnName = "LastName"
MyDataSet.Tables!data.Columns(3).ColumnName = "Address"
MyDataSet.Tables!data.Columns(4).ColumnName = "City"
MyDataSet.Tables!data.Columns(5).ColumnName = "State"
MyDataSet.Tables!data.Columns(6).ColumnName = "ZipCode"
MyDataSet.Tables!data.Columns(7).ColumnName = "Phone_Area"
MyDataSet.Tables!data.Columns(8).ColumnName = "Phone_Prefix"
MyDataSet.Tables!data.Columns(9).ColumnName = "Phone_Suffix"
MyDataSet.Tables!data.Columns(10).ColumnName = "Email"
MyDataSet.Tables!data.Columns(11).ColumnName = "BirthDay"
Response.ClearContent()
'I create the filename I want the data to be saved to and set up the response
Response.AddHeader("content-disposition", "attachment; filename=" & Replace(Session("Key0"), " ", "-") & "-" & Session("Key1") & "-" & Replace(Replace(Trim(Session("Key2")), ".", ""), " ", "-") & ".xls")
Response.ContentType = "application/excel"
Response.Charset = ""
EnableViewState = False
Dim tw As New System.IO.StringWriter
Dim hw As New System.Web.UI.HtmlTextWriter(tw)
'Create and bind table to a datagrid
Dim dgTableForExport As New DataGrid
If MyDataSet.Tables.Count > 0 Then
If MyDataSet.Tables(0).Rows.Count > 0 Then
dgTableForExport.DataSource = MyDataSet.Tables(0) ' .DefaultView
dgTableForExport.DataBind()
'Finish building response
Dim strStyle As String = "<style>.text { mso-number-format:\#; } </style>"
For intTemp As Integer = 0 To MyDataSet.Tables(0).Rows.Count - 1
For intTemp2 As Integer = 0 To MyDataSet.Tables(0).Columns.Count - 1
dgTableForExport.Items(intTemp).Cells(intTemp2).Attributes.Add("class", "text")
Next
Next
End If
End If
dgTableForExport.RenderControl(hw)
Response.Write(style)
' Write the HTML back to the browser.
Response.Write(tw.ToString())
Response.End()
'Close, clear and dispose
MyConnection.Close()
MyConnection.Dispose()
MyConnection = Nothing
I copied and pasted this from one of my projects, it's untested and may contain error but should get you started.
You can use a MemoryStream or to write the file to Response stream using Response.Write method.
Creating an excel file from a data table is fairly easy as you can just create a GridView and bind the table to it.
Here is a code snippet that does what you need.
Public Sub DownloadExcel(outputTable as System.Data.DataTable)
Dim gv As New GridView
Dim tw As New StringWriter
Dim hw As New HtmlTextWriter(tw)
Dim sheetName As String = "OutputFilenameHere"
gv.DataSource = outputTable
gv.DataBind()
gv.RenderControl(hw)
Response.AddHeader("content-disposition", "attachment; filename=" & sheetName & ".xls")
Response.ContentType = "application/octet-stream"
Response.Charset = ""
EnableViewState = False
Response.Write(tw.ToString)
Response.End()
End Sub
There are a few issues with this method:
This doesn't output a native excel file. Instead, it outputs the HTML for a GridView that Excel will detect and notify the user that the content doesn't match the extension. However, it WILL display in Excel correctly if the user selects 'Yes' from the dialog box.
Earlier versions of Firefox and Chrome didn't like this method and instead download the file with a .html extension. I just tested it in both browsers and it worked with the most up to date versions.
Ideally, you should probably use Excel on your webserver to create native spreadsheets, but this will work if you (like me) don't have the means to do so.

Lotus Notes : Not able to access properties file in lotuscript

Hi friends i want to access the properties file from machine from the specified path. For java Agent i used Properties method and extracted the data from the properties file. but now i want it to be done in lotuscript. I tried using properties method but it didnt work so i thought to read properties with the below code.
'Dim ColFileName As String
'ColFileName="C:\abcd.properties"
Open ColFileName For Input As 1
Do While Not EOF(1)
Line Input #1,txt$
MsgBox "TEXT FILE:"+txt$
In properties file i have a written it as
col=start
where i want to get the property of the col using getProperty method in java same way for lotusscript.
I added the above code but it is not working. Can anyone tell what mistake i have committed.
In Options
%Include "lserr.lss" 'This is just a list of constants.
Add these functions somewhere:
%REM
Function fstreamOpenFile(sPath As String, bTruncate As Boolean, bConfirmExists As Boolean) As NotesStream
<dl>
<dt>sPath</dt><dd>Filepath of the file to be opened/created.</dd>
<dt>bTruncate</dt><dd>Boolean. True if file is for output and any existing file should be replaced rather than appended to.</dd>
<dt>bConfirmExists</dt><dd>Boolean. If True, and the opened file is empty, then an ErrFileNotFound error will be thrown.</dd>
</dl>
%END REM
Function fstreamOpenFile(sPath As String, bTruncate As Boolean, bConfirmExists As Boolean) As NotesStream
Dim session as New NotesSession Dim stream As NotesStream
Set stream = session.Createstream()
If Not stream.Open(sPath) Then Error ErrOpenFailed, {Could not open file at "} + sPath + {"}
If bConfirmExists And stream.Bytes = 0 Then Error ErrFileNotFound, {File at "} + sPath + {" is missing or empty.}
If bTruncate Then Call stream.Truncate()
Set fstreamOpenFile = stream
End Function
Function fsPropertyFileValue(sFilePath As String, sPropertyName As String, sDefaultValue As String) As String
On Error GoTo ErrorQuietly
Dim stream As NotesStream
Dim sLine As String
Dim sLeft As String
Dim iLeftLen As Integer
Set stream = fstreamOpenFile(sFilePath, False, True)
sLeft = sPropertyName + "="
iLeftLen = Len(sLeft)
Do
sLine = stream.Readtext
If Left(sLine, iLeftLen) = sLeft Then
fsPropertyFileValue = Right(sLine, Len(sLine) - iLeftLen)
Exit Function
End If
Loop Until stream.Iseos
ReturnDefault:
fsPropertyFileValue = sDefaultValue
Exit Function
ErrorQuietly:
Print Now, Error$
Resume ReturnDefault
End Function
(Notes: I have not tested/debugged fsPropertyFileValue. The html tags in the comment is because, when editing an agent or script library, the designer client will parse and display the HTML tags.)
Then you can use fsPropertyFileValue("C:\abcd.properties", "col", "start") to get the value of the col property within C:\abcd.properties and, if that fails, use "start".

VBA - trying to create XML based on multiple ranges

I am trying to create an output as a XML (save as text file + ".xml").
The layout of the XML is:
<file-info> (forsendelse)
<record-info>
..account#..
</record-info>
</file-info>
I have created a range of fields where the XML is written so that I can just "copy" from the spreadsheet into the text file.
I have tried the following:
With Worksheets("XML_generator")
Set forsendelse1 = .Range("G10:G31")
dat = forsendelse1.Value
Set fs = CreateObject("Scripting.FileSystemObject")
Set myrange1 = .Range("G32:G40")
dat = myrange1.Value
Set fs = CreateObject("Scripting.FileSystemObject")
Set myrange_acc = .Range("G41:G41")
dat = myrange_acc.Value
Set fs = CreateObject("Scripting.FileSystemObject")
Set myrange2 = .Range("G42:G73")
dat = myrange2.Value
Set fs = CreateObject("Scripting.FileSystemObject")
Set forsendelse2 = .Range("G74:G75")
dat = forsendelse2.Value
Set fs = CreateObject("Scripting.FileSystemObject")
Set a = fs.CreateTextFile(FPath & "Request_" & FName & "_" & FDate & ".xml", True)
End With
When I do this I only get the last range ("forsendelse2") in my XML. Does anyone have an idea on how to get this to work?
Please note:
"..account#.." is just one cell in the workbook. This is the main
data to change between exports.
Not using the built in XML generator, since I require blank tags to be exported as well due to validation
Splitting into 5 is so that I going forward can add more than one "record1 + ..account#.. + record2"
In the future I wish the result to look something like this:
<file-info> (forsendelse)
<record-info>
..account#.. (i.e "A2" from sheet)
</record-info>
<record-info>
..account#.. (i.e "A3" from sheet)
</record-info>
</file-info>
But since I haven't tried to do the "while loop" on this yet, firstly I hope someone can help me fix my Range issue :)
Thank you for taking your time!
Best regards
Andreas Petersen
If you want to build up a string from multiple parts then you need to append each part, like this:
dat = "stack"
dat = dat & "overflow"
dat = dat & ".com"
The value of dat will now be "stackoverflow.com".
Your code is overwriting the existing value rather than appending to it:
dat = "stack"
dat = "overflow"
dat = ".com"
The value of dat will now be ".com"
Other issues:
it's not clear why you are creating multiple FileSystemObjects that don't get used (only the last one gets used for anything)
it may be easier to use MSXML2 and build a DOMDocument rather than trying to create the XML as a string

Character changes when importing to Access and exporting to Excel

I'm working on an Access database in which I import csv files converted from xls
Usually this works, but recently one file has some fields where characters change within the field after being imported into Access
For example:
a dash changes to û
a beginning double quote changes to ô
an end double quote changes to ö
From what I have read it has something to do with 7 or 8 bit character codes.. which is not something I really understand.
My questions are, is there any way to prevent this character change or is there something better than what I've tried already?
Or are there any potential problems that I haven't come across with what seems to work in my example below?
Here's what I've tried so far that seems to work
From the original Excel file Save as unicode text file (something new for me)
ActiveWorkbook.SaveAs Filename:= _
"D:\NewFiles\ReportList.txt", FileFormat:=xlUnicodeText _
, CreateBackup:=False
Then import into the database with the following code
DoCmd.TransferText acImportDelim, "ReportList Import Specification", "tbl_ReportList", "D:\NewFiles\ReportList.txt", True
This seems to import the text into the database correctly.
Other people work with the data and then export a new report from Access to Excel.
That changes the font to MS Sans Serif and changes the characters again but not the same changes as when it was imported.
After the Excel report is exported, and I change the font to Arial the characters are correct again.... at least so far.
I haven't run into this character change in the past and my solution seems to work, but I'm not sure if there are other potential problems or if there's anything I missed. I haven't found the answer to this specific question yet.
Thanks for taking time to help with this.
Here is a method that I have used in the past to circumvent the character encoding issues.
I suspect this method should also work between Excel and Access -- although Access is not really something I am familiar with.
This sub specifies the file's full name & path, and a destination for a new filename & path. These could be the same if you want to overwrite existing.
NOTE On a few simple tests, I can't get this to read a file saved as "Unicode" from Excel, but it works perfectly on files saved as "Tab Delimited TXT" files and CSV/comma-separated files, too.
Sub OpenAndSaveTxtUTF8()
Dim txtFileName as String
Dim newTxtFileName as String
txtFileName = "D:\NewFiles\ReportList.txt"
newTxtFileName = "D:\NewFiles\UTF8_ReportList.txt"
WriteUTF8(ReadTextFile(txtFileName), newTxtFileName)
End Sub
This sub calls on two functions which I borrowed from sources credited in the code comments. The WriteUTF8 creates a proper UTF8 file from the contents of ReadTextFile which returns a string of the full file contents.
Function ReadTextFile(sFileName As String) As String
'http://www.vbaexpress.com/kb/getarticle.php?kb_id=699
Dim iFile As Integer
On Local Error Resume Next
' \\ Use FreeFile to supply a file number that is not already in use
iFile = FreeFile
' \\ ' Open file for input.
Open sFileName For Input As #iFile
' \\ Return (Read) the whole content of the file to the function
ReadTextFile = Input$(LOF(iFile), iFile)
Close #iFile
On Error GoTo 0
End Function
This function requires a reference to the ADODB library, or, you can Dim objStream As Object and the code should still work for you.
Function WriteUTF8(textString$, myFileOut$)
'Modified from http://www.vbaexpress.com/forum/showthread.php?t=42375
'David Zemens - February 12, 2013
'Requires a reference to ADODB?
' UTF8() Version 1.00
' Open a "plain" text file and save it again in UTF-8 encoding
' (overwriting an existing file without asking for confirmation).
'
' Based on a sample script from JTMar:
' http://bytes.com/groups/asp/52959-save-file-utf-8-format-asp-vbscript
'
' Written by Rob van der Woude
' http://www.robvanderwoude.com
Dim objStream As ADODB.Stream
' Valid Charset values for ADODB.Stream
Const CdoBIG5 = "big5"
Const CdoEUC_JP = "euc-jp"
Const CdoEUC_KR = "euc-kr"
Const CdoGB2312 = "gb2312"
Const CdoISO_2022_JP = "iso-2022-jp"
Const CdoISO_2022_KR = "iso-2022-kr"
Const CdoISO_8859_1 = "iso-8859-1"
Const CdoISO_8859_2 = "iso-8859-2"
Const CdoISO_8859_3 = "iso-8859-3"
Const CdoISO_8859_4 = "iso-8859-4"
Const CdoISO_8859_5 = "iso-8859-5"
Const CdoISO_8859_6 = "iso-8859-6"
Const CdoISO_8859_7 = "iso-8859-7"
Const CdoISO_8859_8 = "iso-8859-8"
Const CdoISO_8859_9 = "iso-8859-9"
Const cdoKOI8_R = "koi8-r"
Const cdoShift_JIS = "shift-jis"
Const CdoUS_ASCII = "us-ascii"
Const CdoUTF_7 = "utf-7"
Const CdoUTF_8 = "utf-8"
' ADODB.Stream file I/O constants
Const adTypeBinary = 1
Const adTypeText = 2
Const adSaveCreateNotExist = 1
Const adSaveCreateOverWrite = 2
On Error Resume Next
Set objStream = CreateObject("ADODB.Stream")
objStream.Open
objStream.Type = adTypeText
objStream.Position = 0
objStream.Charset = CdoUTF_8
'We are passing a string to write to file, so omit the following line
' objStream.LoadFromFile myFileIn
'And instead of using LoadFromFile we are writing directly from the COPIED
' text from the unsaved/temp instance of Notepad.exe
objStream.WriteText textString, 1
objStream.SaveToFile myFileOut, adSaveCreateOverWrite
objStream.Close
Set objStream = Nothing
If Err Then
WriteUTF8 = False
Else
WriteUTF8 = True
End If
On Error GoTo 0
End Function

Resources