[英]Quicker way to export SQL to Excel in Classic ASP?
A view that takes 1 second in SQL Server Studio for over 13000 rows times out on an ASP page running this code after around 2380 rows. 在大约2380行之后运行此代码的ASP页上,在SQL Server Studio中花费1秒钟超过13000行的视图超时。
Is there a better way to do this? 有一个更好的方法吗? I've been searching for 6 months with no luck. 我一直在寻找6个月没有运气。
Server.ScriptTimeout=200
dim updateNBK
updateNBK = UCase(request.QueryString("SelTABLE"))
dim allstring
allstring = UCase(Request.QueryString("SelTABLE")) & " " & UCase(Request.QueryString("SelNBK"))
allstring = LCase(allstring)
dim checkforinject
If(InStr(allstring, "'")<>0)then
checkforinject = true
Elseif(InStr(allstring, "--")<>0)then
checkforinject = true
End If
If (checkforinject = true) then
Response.Write("<b>Injection Detected</b><br/> You may not enter the following characters: ' or --")
Elseif (checkforinject = false) then
dim strSQL
if(Request.QueryString("submitbutton") = "Download") then
strSQL = "select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = '" & UCase(request.QueryString("SelTABLE")) & "'"
On Error Resume Next
set arn = cnt.execute(strSQL)
dim datastr
dim datahead
datahead = "<table class='bluetable'><thead><tr><td colspan='30'>" & UCase(request.QueryString("SelTABLE")) & " contents</td></tr></thead>"
dim columns
colums = 0
datastr = datastr & "<tbody class='datasheet'><tr class='selectblue'>"
if not arn.EOF then
arn.movefirst
do
On Error Resume Next
datastr = datastr & "<td>" & arn(0) & "</td>"
columns = columns + 1
arn.movenext
loop until arn.EOF
end if
datastr = datastr & "</tr>"
strSQL = "Select * from " & UCase(request.QueryString("SelTABLE"))
if(UCase(Request.QueryString("SelNBK")) <> "") then
strSQL = strSQL & " where SubmitterNBK = '" & UCase(Request.QueryString("SelNBK")) & "'"
end if
set arn = cnt.execute("Select TimestampColumnName from FormsInfo where FormOutput='" & UCase(request.QueryString("SelTABLE")) & "'")
strSQL = strSQL & " ORDER BY " & arn(0) & " desc;"
Response.Write "Test1"
On Error Resume Next
set arn = cnt.execute(strSQL)
dim counter
counter = 0
if not arn.EOF then
arn.movefirst
Response.Write "Test2"
dim cellnum
do
datastr = datastr & "<tr>"
On Error Resume Next
cellnum = 0
'datastr = datastr & "<td>" & arn.value.toString() & "</td>"
do
datastr = datastr & "<td>" & arn(cellnum) & "</td>"
cellnum = cellnum + 1
loop while cellnum < columns
arn.movenext
'Response.Write "TestLoop"
Response.Write "<br/>Loop ran " & counter & " times."
counter = counter + 1
datastr = datastr & "</tr>"
loop until arn.EOF
Response.Write "<br/>Loop ended."
end if
datahead = "<table class='bluetable'>"
Response.Clear
Response.ContentType = "application/vnd.ms-excel" ' arbitrary
Response.AddHeader "Content-Disposition","attachment; filename=" & UCase(request.QueryString("SelTABLE")) & ".xls"
Set adoStream = CreateObject("ADODB.Connection")
adoStream.Open()
adoStream.Type = 2
Response.Write datahead & datastr
Response.Flush
adoStream.Close
Set adoStream = Nothing
Response.End
I suspect your problem lies in the fact that VBScript is horrible with string concatenation - which it appears you are doing a lot of. 我怀疑你的问题在于VBScript在字符串连接方面很糟糕 - 看起来你做的很多。
Although the .NET StringBuilder class is unavailable to VBScript, there are a couple of useful libraries/code samples available. 虽然.NET StringBuilder类对VBScript不可用,但是有一些有用的库/代码示例可供使用。 One example is here: http://www.eggheadcafe.com/articles/20011227.asp 一个例子是: http : //www.eggheadcafe.com/articles/20011227.asp
It may take a little rework of your code, but I bet the performance will drastically improve. 可能需要对代码进行一些修改,但我敢打赌,性能会大幅提升。
Here is an example using the code from the link above. 以下是使用上面链接中的代码的示例。 Note that you will probably want to place the FastString class in an include file so you can reuse it elsewhere. 请注意,您可能希望将FastString类放在包含文件中,以便可以在其他地方重用它。
Dim test : Set test = new FastString
Dim I
For I = 0 To 1000
test.Append("TESTING")
Next
Response.Write test.Concat
Code from the link above: 上面链接中的代码:
Class FastString
Dim stringArray, growthRate, numItems
Private Sub Class_Initialize()
growthRate = 50: numItems = 0
ReDim stringArray(growthRate)
End Sub
Public Sub Append(ByVal strValue)
' next line prevents type mismatch error if strValue is null. Performance hit is negligible.
strValue=strValue & ""
If numItems > UBound(stringArray) Then ReDim Preserve stringArray(UBound(stringArray) + growthRate)
stringArray(numItems) = strValue: numItems = numItems + 1
End Sub
Public Sub Reset
Erase stringArray
Class_Initialize
End Sub
Public Function Concat()
Redim Preserve stringArray(numItems)
concat = Join(stringArray, "")
End Function
End Class
Alternate solution: 替代解决方案:
If you don't mind not having styled cells, you can leverage the "GetRows" functionality of the ADO recordset. 如果您不介意没有样式化单元格,则可以利用ADO记录集的“GetRows”功能。 This little used solution is quite useful in this situation: 在这种情况下,这个小用的解决方案非常有用:
Dim tableRows : tableRows = arn.GetString(,,"</td><td>","</td></tr><tr><td>"," ")
Response.Write "<table class='bluetable'>" & tableRows & "</table>"
So, then, your output becomes: 那么,您的输出变为:
Set arn = cnt.Execute(strSQL)
Response.Clear
Response.ContentType = "application/vnd.ms-excel"
Response.AddHeader "Content-Disposition","attachment; filename=" & UCase(request.QueryString("SelTABLE")) & ".xls"
Dim tableRows : tableRows = arn.GetString(,,"</td><td>","</td></tr><tr><td>"," ")
Response.Write "<table class='bluetable'>" & tableRows & "</table>"
I suspect the string building it what is making it so slow. 我怀疑构建它的字符串是什么让它变得如此之慢。 VBScript is terrible at this. VBScript在这方面很糟糕。
I used to use a class called clsString to do this kind of work. 我曾经使用一个名为clsString的类来完成这种工作。
I think this is it: http://pcdispatchwiki.com/Intranet/includes/funcsSubsClasses.asp 我想是这样的: http : //pcdispatchwiki.com/Intranet/includes/funcsSubsClasses.asp
From memory: 从记忆里:
dim tmpStr : set tmpStr = new clsString
tmpStr.add "Hello"
tmpStr.add vbCRLF
tmpStr.add "World"
dim finalText : finalText = tmpStr.Value
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.