i am new to asp. I have an error when the application try to create a word document.
This happens sometimes, in different machines and some users and I can't get to reproduce in testing environment (Only in production).
And at my workplace is very limited what I can try without asking to production area.
This is the error:
SCRIPT4605: este comando no está disponible para la lectura Este método o propiedad no está disponible porque.
Translation: This command is not available for reading. This method or property is not avaiable
I look for the error in production environment and it seems to be in these five lines, when trying to create a grid and insert a barcode(The creation of the barcode works fine).
Set myRange = objDoc.Range(0, 0)
Set myTable = objDoc.Tables.Add(myRange, 1, 1)
Set myCell = myTable.Cell(1, 1)
myCell.Range.ParagraphFormat.Alignment = 1
myCell.Range.InlineShapes.AddPicture "<%=archivo_temporal%>"
So, the objDoc is created fine, but its seems that does not have (It depends in the user and the machine) the Range() method.
Here is the entire function.
Sub OpenDoc(strLocation)
Dim iOut
Dim oElement
Dim objWord
Dim doc
Set objWord = CreateObject("Word.Application")
objWord.Visible = true
Set objDoc = objWord.Documents.Open(strLocation)
codigo_barras_b64 = DecodeString("<%=codigo_barras_b64%>")
set FSObj = Createobject("Scripting.FileSystemObject")
set file = FSObj.CreateTextFile("<%=archivo_temporal%>", true)
file.write (codigo_barras_b64)
set file = nothing
Set myRange = objDoc.Range(0, 0)
Set myTable = objDoc.Tables.Add(myRange, 1, 1)
Set myCell = myTable.Cell(1, 1)
myCell.Range.ParagraphFormat.Alignment = 1
myCell.Range.InlineShapes.AddPicture "<%=archivo_temporal%>"
iOut = objword.ActiveDocument.Variables.Add("Secretaria", "<%=sLimpiarTextArea(sValor(RSCarat, "secreDescrip"))%> ")'
iOut = objword.ActiveDocument.Variables.Add("Autos", "<%=sLimpiarTextArea(sValor(RSCarat, "expeAutos"))%> ")
iOut = objword.ActiveDocument.Variables.Add("Sobre", "<%=sLimpiarTextArea(sValor(RSCarat, "expeSobre"))%> ")
iOut = objword.ActiveDocument.Variables.Add("En", "<%=sLimpiarTextArea(sValor(RSCarat, "expeEn"))%> ")
iOut = objword.ActiveDocument.Variables.Add("Juez", "<%=sLimpiarTextArea(sValor(RSCarat, "juezNombres"))%> ")
iOut = objword.ActiveDocument.Variables.Add("ExpNro", "<%=sLimpiarTextArea(sValor(RSCarat, "expeNro"))%> ")
iOut = objword.ActiveDocument.Variables.Add("Fecha", "<%=sLimpiarTextArea(sValor(RSCarat, "fechaInicio"))%> ")
objWord.ActiveDocument.Fields.Update
objWord.ActiveDocument.SaveAs "c:\temp\tsj.doc"
objWord.Application.Activate
' Borra el archivo generado
Set MyFile = FSObj.GetFile("<%=archivo_temporal%>")
MyFile.Delete
set FSObj = nothing
Set objWord = Nothing
End Sub
Is anyway that I can insert the barcode in a different way to avoid these lines?
Someone have an idea why this error?
Some hints to look around?
Any help will be appreciated, Thanks!
Related
I have form page that collects data. The user clicks SUBMIT, which goes to a "post page. At the end of this page is the redirect code I am using.
response.redirect( "test.asp?ChecklistID=" + ChecklistID )
For some reason, the result is this.
/test.asp?ChecklistID=4784,%204784
Why is this returning in TWO ID's? I only have ONE record in the 'results' table. And it is '4784'.
Adding the code
<%
'Option Explicit
Dim SQLStmt, sql, RS, ChecklistID, Location, ChecklistDate, Driveup,
ConnectString, conn, objconn
Dim weeds, parking_lot, sidewalk, windows, exterior_trash, door_clean
Dim mats_clean, Notes_page1
Location = Request("Location")
ChecklistDate = Request("ChecklistDate")
Driveup = Request("Driveup")
ChecklistID = Request("ChecklistID")
weeds = Request("weeds")
parking_lot = Request("parking_lot")
sidewalk = Request("sidewalk")
windows = Request("windows")
exterior_trash = Request("exterior_trash")
door_clean = Request("door_clean")
mats_clean = Request("mats_clean")
Notes_page1 = Request("Notes_page1")
ConnectString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" &
Server.MapPath("../xyz/mydatabase.mdb")
Set conn = Server.CreateObject("ADODB.Connection")
conn.open ConnectString
SQLStmt = "SELECT * FROM Results WHERE ChecklistID =" & ChecklistID & " ; "
Set RS = Server.CreateObject("ADODB.Recordset")
RS.open "Results", conn, 3, 3
RS.Update
RS("ChecklistDate") = ChecklistDate
RS("Driveup") = Driveup
RS("weeds") = weeds
RS("parking_lot") = parking_lot
RS("sidewalk") = sidewalk
RS("windows") = windows
RS("exterior_trash") = exterior_trash
RS("door_clean") = door_clean
RS("mats_clean") = mats_clean
RS("Notes_page1") = Notes_page1
RS.Update
RS.close
set RS = nothing
conn.close
set conn = nothing
response.redirect( "test.asp?ChecklistID=" + ChecklistID )
%>
The browser might be retaining some history with response.redirect. Try using Server.Transfer. Or, if it's the same page, you might not have to re-add the query string.
Solved
I had the same hidden field in there twice causing the issue.
Here is a snippet of what I'm working on. Please let me know if I need to post more:
<% # LANGUAGE = VBScript ENABLESESSIONSTATE = False %>
<!--#include file="Connections/ConnectionString.asp" -->
<!--#include file="SqlCheckInclude.asp" -->
<%
Dim LoginTest
LoginTest = ""
If Request.QueryString("Action") = "Login" Then
Dim IsUserNameLocked
Set IsUserNameLocked = Server.CreateObject("ADODB.Recordset")
IsUserNameLocked.ActiveConnection = ConnectionString
sProUserName = Request.Form("ProUserName")
sanitizedProUserName = "'" & Replace(sProUserName, "'", "''") & "'"
Response.Write(sanitizedProUserName)
Response.End()
IsUserNameLocked.Source = "SELECT IL_Date, IL_Timer, IL_NumOfTimes, ProUserName FROM PROFILE WHERE ProUserName =" & sanitizedProUserName
IsUserNameLocked.CursorType = 2
IsUserNameLocked.CursorLocation = 3
IsUserNameLocked.LockType = 3
IsUserNameLocked.Open
if not IsUserNameLocked.eof then
intNumOfIncorrectLogin = IsUserNameLocked("IL_NumOfTimes")
InCorrectLoginDate = IsUserNameLocked("IL_Date")
InCorrectLoginTime = IsUserNameLocked("IL_Timer")
end if
IsUserNameLocked.close
set IsUserNameLocked = nothing
end if
%>
I attempted to convert it to:
If Request.QueryString("Action") = "Login" Then
Dim IsUserNameLocked
Set IsUserNameLocked = Server.CreateObject("ADODB.Recordset")
IsUserNameLocked.ActiveConnection = ConnectionString
strSql = "SELECT IL_Date, IL_Timer, IL_NumOfTimes, ProUserName FROM PROFILE WHERE ProUserName = ?"
strSearch = Request.Form("ProUserName")
set objCommand = Server.CreateObject("ADODB.Command")
objCommand.ActiveConnection = ConnectionString
objCommand.CommandText = strSql
objCommand.Parameters(0).value = strSearch
IsUserNameLocked.results = objCommand.Execute()
IsUserNameLocked.CursorType = 2
IsUserNameLocked.CursorLocation = 3
IsUserNameLocked.LockType = 3
IsUserNameLocked.Open
end if
But this did not work. I have been searching online for the past few hours attempting to find a method that properly works, but I'm getting no functioning results. If someone could please help with an implementation that properly parameterizes and protects against SQL injection, I would be extremely grateful.
According to the docs, you need to .Append a parameter to a Command's parameter collection. Evidence:
>> Set oCmd = CreateObject("ADODB.Command")
>> WScript.Echo "# parameters", oCmd.Parameters.Count
>> oCmd.Parameters(0).Value = "no such thing"
>>
# parameters 0
Error Number: 3265
Error Description: Item cannot be found in the collection corresponding to the requested name or ordinal.
Do you use a global On Error Resume Next?
I have a piece of code that works and do:
Reads a Database , reads a template (template.htm), put data in a new file based in the template (evento.htm), read that file and send an email with the content of the file generated. Code below (I cut the database part):
<%
NomeDoTemplate= "template.htm"
CaminhoDoTemplate= Server.MapPath(NomeDoTemplate)
CaminhoDoTemplateAjustado= Mid(CaminhoDoTemplate,1,InStrRev(CaminhoDoTemplate,"\"))
NomeDoArquivo= "evento.htm"
CaminhoDoArquivo= Server.MapPath(NomeDoArquivo)
Set ManipulacaoDeArquivo= Server.CreateObject("Scripting.FileSystemObject")
Set ObjetoArquivo= ManipulacaoDeArquivo.OpenTextFile(CaminhoDoTemplate, 1)
DadosDoObjetoArquivo= ObjetoArquivo.ReadAll
ObjetoArquivo.Close
DadosDoObjetoArquivo= Replace(DadosDoObjetoArquivo, "[Cliente]", Um)
Set ObjetoArquivo= ManipulacaoDeArquivo.CreateTextFile(CaminhoDoTemplateAjustado & NomeDoArquivo)
ObjetoArquivo.Write(DadosDoObjetoArquivo)
Set ObjetoArquivo= ManipulacaoDeArquivo.OpenTextFile(CaminhoDoTemplateAjustado & NomeDoArquivo, 1)
DadosDoObjetoArquivo= ObjetoArquivo.ReadAll
Dim objCDOSYSMail
Dim objCDOSYSCon
Set objCDOSYSMail = Server.CreateObject("CDO.Message")
Set objCDOSYSCon = Server.CreateObject ("CDO.Configuration")
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.server.com"
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/sendusername") = "user_id"
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "password"
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout") = 30
objCDOSYSCon.Fields.update
Set objCDOSYSMail.Configuration = objCDOSYSCon
objCDOSYSMail.From = "ABC <abc#server.com>"
objCDOSYSMail.To = "sender#gmail.com"
objCDOSYSMail.Subject = "Contato"
objCDOSYSMail.HTMLBody= DadosDoObjetoArquivo
objCDOSYSMail.Send
Set objCDOSYSMail = Nothing
Set objCDOSYSCon = Nothing
%>
I would like to make this simple, skiping the step of generating the file in the disk. I would like to:
Read a Database, reads a template, put data in memory, send the mail with that data in memory.
Thanks
If I see it correctly, all you have to do is skip the part where you save the file and re-read it... I have refactored your code, gave the variables some english names so I could see what's going on, and commented out the lines you don't need:
<%
Dim TemplateName : TemplateName = "template.htm"
Dim TemplateFullPath : TemplateFullPath = Server.MapPath(TemplateName)
Dim TemplatePath : TemplatePath = Mid(TemplateFullPath,1,InStrRev(TemplateFullPath,"\"))
Dim ArchiveName : ArchiveName = "evento.htm"
Dim ArchiveFullPath : ArchiveFullPath = Server.MapPath(ArchiveName)
Dim FSO, TemplateFile, TemplateText
Set FSO = Server.CreateObject("Scripting.FileSystemObject")
Set TemplateFile = FSO.OpenTextFile(TemplateFullPath, 1)
TemplateText = TemplateFile.ReadAll()
TemplateText = Replace(TemplateText, "[Cliente]", Um)
TemplateFile.Close()
' Really simple - to do this in-memory, simply don't save and re-read the file....
' Set TemplateFile = FSO.CreateTextFile(TemplatePath & ArchiveName)
' TemplateFile.Write(TemplateText)
' Set TemplateFile = FSO.OpenTextFile(TemplatePath & ArchiveName, 1)
' TemplateText = TemplateFile.ReadAll
Set TemplateFile = Nothing
Set FSO = Nothing
Dim objCDOSYSMail, objCDOSYSCon
Set objCDOSYSMail = Server.CreateObject("CDO.Message")
Set objCDOSYSCon = Server.CreateObject ("CDO.Configuration")
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.server.com"
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/sendusername") = "user_id"
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "password"
objCDOSYSCon.Fields("http://schemas.microsoft.com/cdo/configuration/smtpconnectiontimeout") = 30
objCDOSYSCon.Fields.update
Set objCDOSYSMail.Configuration = objCDOSYSCon
objCDOSYSMail.From = "ABC <abc#server.com>"
objCDOSYSMail.To = "sender#gmail.com"
objCDOSYSMail.Subject = "Contato"
objCDOSYSMail.HTMLBody= TemplateText
objCDOSYSMail.Send
Set objCDOSYSMail.Configuration = Nothing
Set objCDOSYSMail = Nothing
Set objCDOSYSCon = Nothing
%>
Hope this helps,
Erik
you could use several techniques:
write your own stringbuilder class
use the .net system.io.stringwriter class (yes you can use this from classic asp)
use the adodb.stream object
example stringwriter:
set sw = server.createObject("system.io.stringwriter")
sw.write_12( DadosDoObjetoArquivo )
objCDOSYSMail.HTMLBody = sw.getStringBuilder().toString()
example (adodb.stream):
set stream = server.createobject("ADODB.Stream")
with stream
.Open
.WriteText DadosDoObjetoArquivo
end with
objCDOSYSMail.HTMLBody = stream.ReadText
stream.Close
I recently inherited a website in ASP, which I am not familiar with. Yesterday, one of the pages began to throw an error:
Microsoft VBScript runtime error '800a0009'
Subscript out of range: 'i'
default.asp, line 19
Here is the code from lines 13-27:
<%
set rs = Server.CreateObject("ADODB.Recordset")
rs.open "SELECT * FROM VENDORS_LIST_TBL WHERE inStr('"& dVendorStr &"','|'&ID&'|')", Cn
DIM dTitle(100), dDescription(100), dLink(100)
i = 0 : Do while NOT rs.EOF : i = i + 1
dTitle(i) = rs.fields.item("dTitle").value
dDescription(i) = rs.fields.item("dDescription").value
dLink(i) = rs.fields.item("dLink").value : if dLink(i) <> "" then dTitle(i) = "" & dTitle(i) & ""
if NOT rs.EOF then rs.movenext
Loop
x = i
rs.Close : Set rs = Nothing
%>
Any ideas on what's going on here and how I can fix it?
Thank you!
You've declared dTitle, dDescription and dLink as Arrays with a size of 100. As you are walking through the recordset, you are assigning elements to those arrays. It would appear that you have more than 100 records in your recordset, so the logic is trying to do something like:
dTitle(101) = rs.fields.item("dTitle").value
This will throw an error because your array isn't big enough to hold all of your data.
The "solution" you chose is not very good. What if within 2 years there will be more than 500? You will forget all about this and waste hours yet again.
Instead of fixed size arrays you can just use dynamic arrays:
DIM dTitle(), dDescription(), dLink()
ReDim dTitle(0)
ReDim dDescription(0)
ReDim dLink(0)
i = 0
Do while NOT rs.EOF
i = i + 1
ReDim Preserve dTitle(i)
ReDim Preserve dDescription(i)
ReDim Preserve dLink(i)
dTitle(i) = rs.fields.item("dTitle").value
dDescription(i) = rs.fields.item("dDescription").value
dLink(i) = rs.fields.item("dLink").value
If (Not(IsNull(dLink(i)))) And (dLink(i) <> "") Then
dTitle(i) = "" & dTitle(i) & ""
End If
rs.movenext
Loop
This will start with one (empty) item in each array - for some reason the code seems to need this - then on each iteration one more item will be added, preserving the others.
Note that I've also fixed small issue that might have caused trouble - in case of NULL value in "dLink" field, you would get blank anchors in your HTML because NULL is not empty string in VBScript.
This how GetRows can be used to achieve the same goal.
<%
Function VendorSearch(sVendor)
Dim cn: Set cn = SomeLibraryFunctionThatOpensAConnection()
Dim cmd: Set cmd = Server.CreateObject("ADODB.Command")
cmd.CommandType = adCmdText
cmd.CommandText = "SELECT dTitle, dDescription, dLink FROM VENDORS_LIST_TBL WHERE inStr(?,'|'&ID&'|')"
cmd.Parameters.Append cmd.CreateParameter("Vendor", adVarChar, adParamInput, Len(sVendor), sVendor)
Set cmd.ActiveConnection = cn
Dim rs : Set rs = cmd.Execute()
VendorSearch = rs.GetRows()
rs.Close()
cn.Close()
End Function
Dim arrVendor : arrVendor = VendorSearch(dVendorStr)
Const cTitle = 0, cDesc = 1, cLink = 2
Dim i
For i = 0 To UBound(arrVendor, 2)
If IsNull(arrVendor(cLink, i) Or arrVendor(cLink, i) = "" Then
arrVendor(cTitle, i) = "" & arr(cTitle, i) & ""
End If
Next
%>
Notes:
The Select statement contains only those fields required in the results, the use of * should be avoided
A parameterised command is used to avoid SQL Injection threat from SQL contactenation.
Constants used for field indices into the resulting 2 dimensional array.
Whilst this code replicates the original munging of the title value this is here as an example only. In reality construction of HTML should be left as late as possible and outputing of all such strings as title and description should be passed through Server.HTMLEncode before sending to the response.
I'm trying to update an NText field in SQL 2000 using Classic ASP. Here is the code I'm using to do it. Any one have any pointers on how to maybe speed it up? Or am I stuck with it.
set Cnn = server.CreateObject("ADODB.connection")
Cnn.ConnectionString = Application("Cnn_ConnectionString")
Cnn.open
set rs = server.CreateObject("ADODB.Recordset")
rs.CursorType = adoOpenDynamic
rs.LockType = adLockOptimistic
conChunkSize = 100
rs.Open "MyTable",Cnn, , , adCmdTable
rs.Find "MyDataId=" & request("DataId"),,adSearchForward,1
lngOffset = 0
lngLogoSize = len(request("txtMyEntry"))*2
Do while lngOffset < lngLogoSize
varChunk = LeftB(RightB(request("txtMyEntry"), lngLogoSize - _
lngOffset), conChunkSize)
rs("MyDataField").AppendChunk varChunk
lngOffset = lngOffset + conChunkSize
Loop
rs.Update
rs.Close
Oh and this code is almost verbatim from the MSDN site.
First I would eliminate the chunking which is so 90's.
Then there is:-
rs.Open "MyTable",Cnn, , , adCmdTable
rs.Find "MyDataId=" & request("DataId"),,adSearchForward,1
Yikes! You'd like to think that ADO intelligently asked SQL server to find that record based on the indexed MyDataId field but bet it doesn't. Its most likely pulling the entire contents of the table across until the record is arrived at.
This really should be done with an UPDATE T-SQL statement and an ADODB.Command object.
Set cmd = Server.CreateObject("ADODB.Command")
cmd.ActiveConnection = cnn
cmd.CommandType = 1 '' // adCmdText
cmd.CommandText = "UPDATE MyTable SET MyDataField = ? WHERE MyDataId = ?"
cmd.Parameters.Append cmd.CreateParameter("dataField", 203, 1, Len(txtMyEntry), txtMyEntry) '' // 203 = asLongVarWChar, 1 = adParamInput
cmd.Parameters.Append cmd.CreateParameter("id", 3, 1, , CInt(DataID)) '' // 3 = adInteger
cmd.Execute