Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Making resultsets available as downloadable files

Status
Not open for further replies.

Ian2

IS-IT--Management
Feb 4, 2003
7
ZA
Hi

I have an ASP page that gets data from a database and displays the resultset.

How would I add a button to make that resultset downloadable to the desktop (possibly via a 'save as' dialogue box)?

Regards
Ian
 
This should be possible. The basic process could work something like this:

1) open recordset
2) loop through RS and use the FileSytemObject to write each row as a line to a text file (possible adding commas to separate fields?)
3) add static link to the text file on your page (<a href=&quot;textfile.txt&quot;>)

Basically your link always goes to the same file, you just change the actual file within the page code. --James
 
Thanks James

As you can see, I came across exactly the same solution. Now just need to figure out the mismatch errors... :-}

Ian
 
If this helps, I have posted the code that I use for creating an Excel file using FSO. I have only included a snippet but you should be able to get the gist - I have used two subs - one called display_files() which lists the files created, and one called create_spreadsbeet which does the actual Excel bit:

Code:
'#########################
sub display_files()
'#########################
'open the file objects
set objfs = Server.CreateObject
(&quot;Scripting.FileSystemObject&quot;)
FolderPath=request.ServerVariables(&quot;APPL_PHYSICAL_PATH&quot;) 
& &quot;registrations/&quot; 'specify filepath from root
set objfolder = objfs.GetFolder(FolderPath)
set objFiles = objFolder.Files

<html>
<body>
<table align=&quot;center&quot; valign=&quot;top&quot; width=&quot;100%&quot; border=&quot;0&quot;>
<%if file <> &quot;&quot; then%>
<TR><TD>
<input type=&quot;button&quot; value=&quot;Download current spreadsheet >>&quot; name=&quot;download&quot; onClick=&quot;javascript:window.open
('registrations/<%=file%>','registrations','toolbar=1,location=1,directories=1,menuB
ar=1,scrollbars=1,resizable=1,status=1,width=650,height=550,
left=10,top=10');&quot;>
<BR>[Filename: <%=file%>]</td></tR>  
<%end if 'if file <> &quot;&quot;%>
<table border=&quot;1&quot; bgcolor=&quot;#FFFFFF&quot; cellspacing=&quot;0&quot; 
cellpadding=&quot;2&quot; width=&quot;600&quot;>
<caption><B>Registration files</b></caption>
<TR>
<TH>Name</th>
<th>Size (kb)</th>
<th>Created</th>
</tr>
<%for each objFile in objFiles%>
<TR>
<TD><a href=&quot;reg_data/<%=objFile.Name%>&quot; target=&quot;_blank&quot;><%
=objFile.Name%></a></td>
<TD><%=objFile.Size%></td>
<TD><%=objFile.DateCreated%></td>
</tr>
<%next%>
</table>
</body>
</html>
'#########################
end sub 'display_files()
'#########################

'#########################
sub create_spreadsheet(file)
'#########################
'create the database connection
'(DB_CONNECTIONSTRING not included here)
set objconn=Server.CreateObject(&quot;ADODB.Connection&quot;)
objconn.open DB_CONNECTIONSTRING
set objrs=Server.CreateObject(&quot;ADODB.Recordset&quot;)
'get the data from the database you wish to display
SQL=&quot;SELECT * FROM tblregistrations WHERE IsNull
(cleared_flag) ORDER BY id asc&quot;

set objrs=objconn.execute(SQL)
if not objrs.BOF and not objrs.EOF then

'base the spreadsheet name on the date (to keep it unique)
path=Server.mappath(&quot;.&quot;)

file=day(date)&month(date)&year(date)&&quot;-&quot;&hour(time)&minute
(time)&second(time)&&quot;-registrations.xls&quot;
range=day(date)&month(date)&year(date)&&quot;registrations&quot;

'create the file
set fso=CreateObject(&quot;scripting.filesystemobject&quot;)
set act=fso.CreateTextFile(server.mappath
(&quot;registrations/&quot;&file),false)

'write the data to the spreadsheet
strline=&quot;&quot;
For each x in objrs.Fields
strline=strline & x.Name & chr(9)
next
act.writeline strline



do while not objrs.EOF
strline=&quot;&quot;  
for each x in objrs.Fields
strline=strline & x.value & chr(9)
next
act.writeline strline

'loop thru
objrs.movenext
loop

'close the connections
act.close
end if 'if bof and eof
objrs.close
objconn.close
set objrs=nothing
set objconn = nothing
'##############################
end sub 'create_spreadsheet()
'##############################

(If you don't know this, you can call a sub using:
call subname()
)

Cheers
Biffy
;)
 
Thanks James (and Biffy)

The page is rather complex and the error does not appear to be related to the solution, but to the way the function is called.

To simplify -

<code>

<%@ Language=VBScript %>
<!--#include file=&quot;..\databaseconnections.inc&quot; -->

<%
radio = Request.querystring(&quot;radio&quot;)

if radio = &quot;Callout&quot; then
strParams = chr(34) & &quot;where....&quot; & chr(34)
set rs.cnn.execute(&quot;exec getdata&quot; & strparams)
end if
%>

<HTML>
<HEAD>
<META NAME=&quot;GENERATOR&quot; Content=&quot;Microsoft Visual Studio 6.0&quot;>
<TITLE>Callout Reports</title>
</HEAD>


<BODY>

<FORM name=&quot;TopForm&quot; method=&quot;Post&quot;>

<TABLE WIDTH=65% BORDER=0 CELLSPACING=1 CELLPADDING=1 align=center >
<TR>
<TD><INPUT type=&quot;button&quot; id=DownloadData name=button_DownloadData value=&quot;Download Data&quot;></TD>
</TR>
</TABLE>
</FORM>


<form name=&quot;BottomForm&quot; method=&quot;Post&quot;>

<!-- Table for results ------------------------------------------------------>
<TABLE>
<TR> Headings
</TR>

<%
Line=1
Do While NOT rs.EOF
Fieldname = rs.field(name).value
%>

<TR>
<TD><%=field%></TD>
</TR>

<%
rs.movenext
line=line+1
if line=1000 then
exit do
end if
Loop
%>


</TABLE>
</form>


</BODY>
</HTML>


<Script ID=clientEventHandlersVBS Language=&quot;VBscript&quot;>

Public Sub button_DownloadData_OnClick
CreateCSVFile()
End Sub

</SCRIPT>


<SCRIPT Language=&quot;VBScript&quot; runat=&quot;server&quot;>
Function GenFileName()
dim fname
Select Case radio
Case &quot;Callout&quot;
fname = &quot;Callout&quot;
GenFileName = fname
Case .....
End select
End Function

Function CreateCSVFile()
strFile = GenFileName()
Set fs = Server.CreateObject(&quot;Scripting.FileSystemObject&quot;)
Set a = fs.CreateTextFile(server.MapPath(&quot;.&quot;) & &quot;\CSV\&quot; & strFile & &quot;.csv&quot;,True)

For i = 0 To RS.fields.Count-1
strtext = chr(34) & RS(i).name & chr(34) & &quot;,&quot;
a.Write(strtext)
next
a.Writeline()

If Not RS.EOF Then
Do Until RS.EOF
For i = 0 To RS.fields.Count-1
strtext = chr(34) & RS.fields(i) & chr(34) & &quot;,&quot;
a.Write(strtext)
Next
a.Writeline()
RS.MoveNext
Loop
End If
a.Close
Set fs=Nothing
Response.Write(&quot;Click <A HRef=../Reports/CSV/&quot; & strFile & &quot;.csv>Here</A> to get CSV file&quot;)
End Function
</Script>

</code>

There may be some minor slips as I have cannibalised it to take out the extraneous detail. The core is in how the functions are called. Even if I remove the contents -

Function CreateCSVFile()
End Function

it still returns a Type Mismatch error.
 
Ok, the problem here is your attempting to run a server-side function from a client-side event. This is not something that can be done. Once the server has executed any code it has it is finished and deallocates any memory it was using. At this point the client is just receiving the last portion of the page from the server and the onLoad event wwill fire. Since the Server is no longer processing at this point it is not possible to call the server-side code from the client(not to mention the inherrent communication issues and such that result). What you will need to do is on the event where you would want to create the CSV file you need to submit the page to a new page that actually does the CSV creation and such in ASP.

I would tend to go something similar to Biffy's solution, where you actually write the file on the fly and either display it or allow the user to download it. This means you don't have to worry about several people requesting the page at once because it will be written on the fly each time. The advantage of this is you don't have to worry about a naming technique for you text files. If you were to go with a hardcoded name it would be possible that different people would request the page at the same time, causing that file to be overwritten several times and then the same copy distributed to everyone. If you use a dynamic scheme you have to make sure you delete the files when your done giving them to the user or they will fill up the server with garbage. In any case there is the possibility that someone is going to copy the link into an email or such and expect it to still be there the next time they need it (ie, a lazy person that doesn't want to waste space on their own hard drive).

-Tarwn ________________________________________________
Get better results for your questions: faq333-2924
Frequently Asked ASP Questions: faq333-3048
 
Thanks for the assistance Gents. Will have to digest all this.

Another step in the learning process...

Ian
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top