I want to create a classic asp (vbscript) function that replaces all 'returns' that occur between double quotes.
The input string is 'csv' like:
ID;Text;Number
1;some text;20
2;"some text with unwanted return
";30
3;some text again;40
I want to split the string on chr(13) (returns) to create single rows in an array. It works well, except for the unwanted chr(13) that is contained in the text of id 2.
I hope someone could help.
Fundamentally, this is going to be difficult to do as you won't be able to tell whether the carriage return is a valid one or not. Clearly the ones after 20 and 30 are valid.
An approach I would would be to scan through each line in the file and count the commas that occur. If it's less than 3, then append the next line and use the concatenated string. (This of course assumes your CSV structure is consistent and fixed).
What I would really be asking here is why is the CSV like this in the first place? The routine that populates this should really be the one stripping the the CRs out.
Think of a CSV file like a very crude database or spreadsheet. When cosidering the above file, it is clear that the 'Database'/'Spreadsheet' is corrupt.
If the program that generates this is correupting it, then what extent should the reading application goto to correct these defects? I'm not sure that Excel or SQL Server (for example) would go to great lengths to correct a corrupt data source.
Your text file is just like a CSV file but with semicolons not commas. Use ADO to grab the data and it will handle the line breaks in fields.
Specifically (In ASP VBScript):
On Error Resume Next
Const adOpenStatic = 3
Const adLockOptimistic = 3
Const adCmdText = &H0001
Set objConnection = Server.CreateObject("ADODB.Connection")
Set objRecordSet = Server.CreateObject("ADODB.Recordset")
strPathtoTextFile = server.mappath(".") 'Path to your text file
objConnection.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source=" & strPathtoTextFile & ";" & _
"Extended Properties=""text;HDR=YES;FMT=Delimited"""
objRecordset.Open "SELECT * FROM test.txt", _
objConnection, adOpenStatic, adLockOptimistic, adCmdText
Do Until objRecordset.EOF
Response.Write "ID: " & objRecordset.Fields.Item("ID") & "<br>"
Response.Write "Text: " & objRecordset.Fields.Item("Text") & "<br>"
Response.Write "Number: " & objRecordset.Fields.Item("Number") & "<br>"
objRecordset.MoveNext
Loop
Code sample is modified from Microsofts' Much ADO About Text Files.
This script assumes your data text file is in the same directory as it (the asp file). It also needs a schema.ini file in the same directory as your data text file with the data:
[test.txt]
Format=Delimited(;)
Change text.txt in both code samples above to the name of your text file.
If the unwanted CRLF always occurs inside a text field (inside double quotes), it would not be very difficult to use a regular expression to remove these. Vbscript has a regex engine to its disposal: http://authors.aspalliance.com/brettb/VBScriptRegularExpressions.asp
It all depends ofcourse on how familiar you are with Regular Expressions. I couldn't think of the proper syntax off the top of my head, but this is probably quite easy to figure out.
The solution is pretty easy:
str = "Some text..." & chr(13)
str = REPLACE(str,VbCrlf,"")
The secret is use VbCrlf. For me I use a simple function for solve the problem and add this in my framework.
FUNCTION performStringTreatmentRemoveNewLineChar(byval str)
IF isNull(str) THEN
str = ""
END IF
str = REPLACE(str,VbCrlf,"")
performStringTreatmentRemoveNewLineChar = TRIM(str)
END FUNCTION
Of course this will remove all new lines character from this string. Use carrefully.
Related
I want to insert an if statement in a cell through vba which includes double quotes.
Here is my code:
Worksheets("Sheet1").Range("A1").Value = "=IF(Sheet1!B1=0,"",Sheet1!B1)"
Due to double quotes I am having issues with inserting the string. How do I handle double quotes?
I find the easiest way is to double up on the quotes to handle a quote.
Worksheets("Sheet1").Range("A1").Formula = "IF(Sheet1!A1=0,"""",Sheet1!A1)"
Some people like to use CHR(34)*:
Worksheets("Sheet1").Range("A1").Formula = "IF(Sheet1!A1=0," & CHR(34) & CHR(34) & ",Sheet1!A1)"
*Note: CHAR() is used as an Excel cell formula, e.g. writing "=CHAR(34)" in a cell, but for VBA code you use the CHR() function.
Another work-around is to construct a string with a temporary substitute character. Then you can use REPLACE to change each temp character to the double quote. I use tilde as the temporary substitute character.
Here is an example from a project I have been working on. This is a little utility routine to repair a very complicated formula if/when the cell gets stepped on accidentally. It is a difficult formula to enter into a cell, but this little utility fixes it instantly.
Sub RepairFormula()
Dim FormulaString As String
FormulaString = "=MID(CELL(~filename~,$A$1),FIND(~[~,CELL(~filename~,$A$1))+1,FIND(~]~, CELL(~filename~,$A$1))-FIND(~[~,CELL(~filename~,$A$1))-1)"
FormulaString = Replace(FormulaString, Chr(126), Chr(34)) 'this replaces every instance of the tilde with a double quote.
Range("WorkbookFileName").Formula = FormulaString
This is really just a simple programming trick, but it makes entering the formula in your VBA code pretty easy.
All double quotes inside double quotes which suround the string must be changed doubled. As example I had one of json file strings : "delivery": "Standard",
In Vba Editor I changed it into """delivery"": ""Standard""," and everythig works correctly. If you have to insert a lot of similar strings, my proposal first, insert them all between "" , then with VBA editor replace " inside into "". If you will do mistake, VBA editor shows this line in red and you will correct this error.
I have written a small routine which copies formula from a cell to clipboard which one can easily paste in Visual Basic Editor.
Public Sub CopyExcelFormulaInVBAFormat()
Dim strFormula As String
Dim objDataObj As Object
'\Check that single cell is selected!
If Selection.Cells.Count > 1 Then
MsgBox "Select single cell only!", vbCritical
Exit Sub
End If
'Check if we are not on a blank cell!
If Len(ActiveCell.Formula) = 0 Then
MsgBox "No Formula To Copy!", vbCritical
Exit Sub
End If
'Add quotes as required in VBE
strFormula = Chr(34) & Replace(ActiveCell.Formula, Chr(34), Chr(34) & Chr(34)) & Chr(34)
'This is ClsID of MSFORMS Data Object
Set objDataObj = CreateObject("New:{1C3B4210-F441-11CE-B9EA-00AA006B1A69}")
objDataObj.SetText strFormula, 1
objDataObj.PutInClipboard
MsgBox "VBA Format formula copied to Clipboard!", vbInformation
Set objDataObj = Nothing
End Sub
It is originally posted on Chandoo.org forums' Vault Section.
In case the comment by gicalle ever dies:
I prefer creating a global variable:
Public Const vbDoubleQuote As String = """" 'represents 1 double quote (")
Public Const vbSingleQuote As String = "'" 'represents 1 single quote (')
and using it like so:
Shell "explorer.exe " & vbDoubleQuote & sPath & vbDoubleQuote, vbNormalFocus
I'm trying to append a character string from a variable to the end of lines in a CSV. However, line feeds are being replaced by the string. So if the original line is:
fieldcharacters1,fieldcharacters string starts on one line
and continue after a line feed,fieldcharacters3
(where the blank line is a line feed)
and I want to append "fieldcharacter4" (without quotes) to the end of the line, it should show up like this:
fieldcharacters1,fieldcharacters string starts on one line
and continue after a line feed,fieldcharacters3,fieldcharacter4
But instead it's ending up like this:
fieldcharacters1,fieldcharacters string starts on one
line,fieldcharacter4 ,fieldcharacter4 and continue after a line
feed,fieldcharacters3,fieldcharacter4
Here's the code I have. I also tried a Do Until Loop using objCurrentFile.AtEndOfStream, but it didn't work either.
Set tsOut = objFSO.CreateTextFile(strCSV, FOR_WRITING)
strLine = objCurrentFile.ReadAll
objCurrentFile.close
strInsertText = ",testing123123" & chr(013)
WScript.Echo "Text to be appended= " & strInsertText
strNewText = Replace(strLine, Chr(013), strInsertText )
tsOut.Write strNewText
There are three end-of-line markers:
Linefeed|vbLf|Chr(10)|/n
CarriageReturn|vbCr|chr(13)|/r
CarriageReturn+Linefeed|vbCrLf|Chr(13) & Chr(10)|/r/n
When reading from a file, .ReadLine() will remove /n or /r/n, but not /r (see here); .ReadLine(), however, will return all contents of the file.
A simple model of your problem: you have a .CSV containing fields with embedded \r's and \r\n as eol; when 'trying to append a character string from a variable to the end of lines' via Replace, the embedded \r's are affected too:
>> sLine = "field 1,... one line\rand ...field 3\r\n"
>> WScript.Echo Replace(sLine, "\r", "[,append]")
>>
field 1,... one line[,append]and ...field 3[,append]\n
You may get away with Replacing \r\n:
>> WScript.Echo Replace(sLine, "\r\n", "[,append]")
>>
field 1,... one line\rand ...field 3[,append]
and dealing with an eventual replacement of a trailing \r\n in your file. If you can loop over the .CSV lines, append/concatenate (instead of using .Replace) the extra data and the proper eol marker (perhaps via .WriteLine).
The first approach will fail if the eol- and the embedded marker are identical. In that case (and probably in general) using the ADO Text driver to deal with .CSVs is a much better option.
(BTW: read the docs to learn why
objFSO.CreateTextFile(strCSV, FOR_WRITING)
is wrong)
Update wrt comment:
From your comment I conclude that your .CSV use \r\n for eol and embedded (paragraph?) marker. So Replace won't work:
>> sLine = "field 1,... one line\r\nand ...field 3\r\n"
>> WScript.Echo Replace(sLine, "\r\n", "[,append]")
>>
field 1,... one line[,append]and ...field 3[,append]
When using .ReadLine() you also have to expect to get 'short lines' terminated at the embedded \r\n. So your options are:
Talk to the creator of the .CSV and ask her to use different markers for the embedded vs. the eol marker. You can then use Replace(.ReadAll(), eol, extra & eol, provided you deal with the 'spurious replacement on the last (empty) line' mentioned above.
Depending on the format/layout/content of the .CSV - quoted strings, field separator embedded in (quoted) fields, data types, line length(es), position of \r\n in a line - you may be able to write a custom RegExp replacement function or a full-fledged parser that does the job (cf here). To help you with that I'd need a decent desription of the .CSV (think schema.ini) and representative sample data.
Use ADO text driver (start your research here, but don't stop there). The risk: I'm not sure whether the driver can cope with (mis)using the eol marker embedded.
A rough idea:
After a short look at the sample data, I can confirm that \r\n is used for eol and paragraph in some of the quoted fields. First tests show that the ADO text driver can deal with that.
But because the first field contains quoted IP Adresses, you can distinguish between eol (\r\n followed by " (or "IP Address")) and paragraph (\r\n not followed by " (or "IP Address")). If there are no " in the 'paragraphed' fields, a (not so) simple Replace for \r\n" on the .ReadAll will solve the problem; otherwise a RegExp refering to the IP Address would be needed.
Demo code:
Option Explicit
Dim sCsv : sCsv = Replace(Join(Array( _
"'1.2.3.4','line1\r\nline2',1,'whatever'" _
, "'5.6.7.8','linea\r\nlineb',2,'pipapopu'" _
, "" _
), "eol"), "'", """")
WScript.Echo "faked .CSV (embedded \r\r, EOL \r\n)"
WScript.Echo Replace(sCsv, "eol", "\r\n" & vbCrLf) ' for display
sCsv = Replace(Replace(sCsv, "eol", vbCrLf), "\r\n", vbCrLf) ' 'real data'
WScript.Echo "raw display of .CSV"
WScript.Echo sCsv
If False Then
Dim re : Set re = New RegExp
re.Global = True
re.Pattern = "(\r\n""\d+(\.\d+){3}"")" ' EOL followed by "IP Address" of next line
' dirty hack to append to last line
sCsv = sCsv & """0.0.0.0"""
sCsv = re.Replace(sCsv, ",""append""$1")
' remove trailing junk (\r\n"IP Address")
sCsv = Left(sCsv, Len(sCsv) - 11)
Else
' dirty hack to append to last line
sCsv = sCsv & """"
sCsv = Replace(sCsv, vbCrLf & """", ",""append""" & vbCrLf & """")
' remove trailing junk (\r\n")
sCsv = Left(sCsv, Len(sCsv) - 3)
End If
WScript.Echo "raw display of .CSV after appending"
WScript.Echo sCsv
output (for both methods):
cscript 24673618.vbs
faked .CSV (embedded \r\r, EOL \r\n)
"1.2.3.4","line1\r\nline2",1,"whatever"\r\n
"5.6.7.8","linea\r\nlineb",2,"pipapopu"\r\n
raw display of .CSV
"1.2.3.4","line1
line2",1,"whatever"
"5.6.7.8","linea
lineb",2,"pipapopu"
raw display of .CSV after appending
"1.2.3.4","line1
line2",1,"whatever","append"
"5.6.7.8","linea
lineb",2,"pipapopu","append"
I was just testing my database and I realized that I run into problems wherever a text entry in my database contains a ' character (single quote). My solution for now is that before any .execute operations on a string, I call escape(string, "'", " "'" ").
Summarized example below:
qr = "INSERT INTO tblExample VALUES ( " & "'" & me.testparam & "'" & ");"
qr = Replace(qr, "'", " "'" ")
db.execute qr
'also tried qr = "INSERT INTO tblExample VALUES ( " & "'" & replace(me.testparam,"'"," ") & "'" & ");"
This was what I assumed to be the correct workaround to prevent errors from values such as Tourette's.
There's two problems with this. First of all, it's not working. Second, I have over 50 locations in code throughout my app where I call the statement db.execute qr where qr is a string that could potentially contain a single quote. I need the field in the table to contain the single quote, so I can't just replace it with a space or something similar.
Two part question:
Is there a better solution than going through all of my code calling Replace on every string that is to be executed as a query?
Why is my current implementation failing? - I still get syntax error in query expression even when escaping the single quote to a space.
First examine these 2 lines.
"VALUES ( " & "'" & me.testparam & "'" & ");"
"VALUES ( '" & me.testparam & "');"
Both will produce the exact same string. The difference for me is that my brain comprehends the second version faster.
Now, here is what the comments are telling you to do ... replace each single quote in your source string with two single quotes. I added Debug.Print so you can view the finished string in the Immediate window (go there with Ctrl+g) ... you can then see the actual string rather than trying to imagine what it looks like.
qr = "INSERT INTO tblExample VALUES ( '" & _
Replace(Me.testparam, "'", "''" & "');"
Debug.Print qr
db.Execute qr, dbFailOnError
Since I assumed db is a DAO.Database object variable, I included the dbFailOnError option. You should include an error handler in your code to deal with any problems dbFailOnError exposes.
When you run into trouble with a VBA function in a query, drop to the Immediate window and test your function expression there. This one triggers a compile error, "Expected: list separator or )":
? Replace("Tourette's", "'", " "'" ")
But this one works:
? Replace("Tourette's", "'", "''")
Tourette''s
I mentioned that because it's useful in general, and also because your title starts with "Escaping unwanted characters, mainly single quotes". So if you want to remove/replace other characters, not just single quotes, experiment in the Immediate window until you find a Replace() expression which works. Then use that expression in your query.
For example, if unwanted characters include line breaks ...
MyString = "foo" & vbCrlf & "bar" : ? MyString
foo
bar
? Replace(MyString, Chr(13) & Chr(10), " ")
foo bar
Note: I used Chr(13) & Chr(10) rather than vbCrlf as the find target because the db engine can use the Chr() function but doesn't know about the named constant (vbCrlf).
Your query is failing because you have not said where to insert :
Dim qd As QueryDef
qr = "INSERT INTO tblExample (AText) VALUES ( [avalue] );"
Set qd = CurrentDB.CreateQueryDef("",qr)
qd.Parameters("avalue").Value = me.testparam
qd.Execute dbFailOnError
Another method is to define a quote as constant (Const Quote = """") and use that to build SQL Statements. It is not possible to define a quote as Const Quote = Chr(34) as a constant definition can't be based on a function so one has to use four double quotes in a row. The third quote is what you are saving, the second quote is to excape the third quote and the first and last quote are because the value you are assigning is a string.
You will then be able to build SQL statements such as:
SQL = SELECT * FROM tblSyndromes
WHERE Syndrome = " & Quote & "Tourette's" & Quote & ";"
It will no longer matter that there are single quotes in your data.
I don't use parameters as if I upscale my database to sql server and convert my queries to pass-through queries, I can't use parameters. I rarely upscale but I write all my code with that assumption. Also if your query is not working as expected, how do find out what went wrong. If I have a variable called SQL, then I can always print the SQL statement and run it in a new query to see what it does.
I need to make a "static html" FAQ-like-document for internal use on a project.
I put all the items in an Access 2007 Database as records (question, answer, category) and then built a report that uses a sub-report to create a table of contents as internal links and then lists all of the questions and answers. This report is a bunch of text-areas with dynamically generated html code(apparently I don't have enough cred to post images yet so http://i115.photobucket.com/albums/n299/SinbadEV/ReportCapture.png)... I just export the report to a text file and then rename it to .html and open it in a browser.
I'm thinking there has to be a less evil way to do this.
I have now used an idea from SinbadEV and awrigley to create professionally looking HTML-reports in MS Access 2007. In my case I had to use yet another trick:
I found out, that due to some bug in MS Access it does not save the report correctly to txt format. Sometimes it drops a lot of information, even though it is displayed on the screen. I have also seen problem, mentioned here that sometimes access mixing lines. It seem to depend on several factors, e.g. whether report and a data span across pages in MS Acess report.
However I found, that exporting to *.rtf does work correctly. Therefore the approach is to craft MS Acess report, which, when saved into text file would create an HTML code (just like described by SinbadEV ), however you 1st need to save it to *rtf. After that you need to use MS Word automation to convert from *.rtf to txt file and to give it .html extention (In reality it does not take too much efforts).
Instead of MS word automation one can probably also use tool like Doxillion Document Converter to convert from rtf to text format from command line.
You can see database with this feature in the Meeting minutes, Issues, Risks, Agreements, Actions, Projects Tracking tool (http://sourceforge.net/projects/miraapt/).
There's an ExportXML method in the Application object, which can export database objects (tables,reports etc.) in XML. You'll need a XSL style sheet or a XSTL document if you want to format it for a browser:
http://msdn.microsoft.com/en-us/library/bb258194(v=office.12).aspx
I'd say this is the "canonical" way to do it. OTOH writing XSL & XSTL isn't like a fun thing to do and if you HTML generator works, then you should simply keep it like it is. (Actually, it's a nice trick IMHO).
I don't see anything inherently "evil" in what you are doing. I wrote an article for (the now defunct magazine) Smart Access that uses a similar technique for a different reason. The HTML report was a by product. Essentially, my technique allows using Access to create very extensive word documents that flow like typed text rather than looking like reports created using boxes.
You can still read the article on MSDN:
Extending Access Reports With Word and HTML
The trick was to generate HTML using a report like you are doing, then using automation, open the .html file in Word and save it as RTF.
We used the technique to create a 300 page directory for the Diocese of York. It worked flawlessly.
Just in case you want to go the VBA way: I wrote a few functions that can make it quite easy:
create queries containing the data you want to output,
then open the query and loop through all records, outputting data to text file using function rRsToXml below.
Option Compare Database
Option Explicit
Function fRsToXml(rs As Recordset, Optional ignorePrefix As String = "zz", _
Optional ignoreNulls As Boolean = False) As String
'<description> Returns an XML string with all fields of the current record,
' using field names as tags.
' Field names starting with "zz" (or other special prefix) are ignored</description>
'<parameters> rs: recordset (byRef, of course)</parameters>
'<author> Patrick Honorez - www.idevlop.com </author>
Dim f As Field, bPrefLen As Byte
Dim strResult As String
bPrefLen = Len(ignorePrefix)
For Each f In rs.Fields
If Left(f.Name, bPrefLen) <> ignorePrefix Then 'zz fields are ignored !
If (Not ignoreNulls) Or (ignoreNulls And Not IsNull(f.Value)) Then
strResult = strResult & xTag(f.Name, f.Value) & vbCrLf
End If
End If
Next f
fRsToXml = strResult
End Function
Function xTag(ByVal sTagName As String, ByVal sValue, Optional SplitLines As Boolean = False) As String
'<description> Create an xml node and returns it as a string </description>
'<parameters> <sTagName> name of the tag </sTagName>
' <sValue> string to embed </sValue>
' <SplitLine> True to include CrLf at the end of each line
' (optional - default = False) </SplitLine></parameters>
'<author> Patrick Honorez - www.idevlop.com </author>
'<note> Make sure sValue does not contains XML forbidden characters ! </note>
'<changelog>
'</changelog>
Dim strNl As String, intAmp
If SplitLines Then
strNl = vbCrLf
Else
strNl = vbNullString
End If
xTag = "<" & sTagName & ">" & strNl & _
Nz(sValue, "") & strNl & _
"</" & sTagName & ">" '& strNl
End Function
Function CleanupStr(strXmlValue) As String
'<description> Replace forbidden char. &'"<> by their Predefined General Entities </description>
'<author> Patrick Honorez - www.idevlop.com </author>
Dim sValue As String
If IsNull(strXmlValue) Then
CleanupStr = ""
Else
sValue = CStr(strXmlValue)
sValue = Replace(sValue, "&", "&") 'do ampersand first !
sValue = Replace(sValue, "'", "'")
sValue = Replace(sValue, """", """)
sValue = Replace(sValue, "<", "<")
sValue = Replace(sValue, ">", ">")
CleanupStr = sValue
End If
End Function
I used to spoof the report generator into making html documents for me but this approach has limitations. Firstly when you run the report, it generates rather ugly html and not a print ready report. There is more work after running the report to transform the report into a nice html document that can be opened in a word processor and then saved as a regular document. LibreOffice often is a better recipient of generated html documents than ms-word but occasionally LibreOffice fails to do the job (for a while it had issues with linked images). Word processors ignore css styles so don't bother with styles, direct formatting still works well, particularly for text is tables. If all the exported data is inside a html table, then use LibreOffice as LibreOffice can generate a table of contents based on h1, h2, h3 headings, whereas ms-word cannot.
These days, I just write the entire report as a procedure in a VBA standard module. I still do not use object oriented code and there is no reason to here. Reports written entirely in VBA can be far more sophisticated that what the standard ms-Access report designer can produce. Report designer reports take a lot of tinkering to get the format just right and this consumes time. For complex reports, the VBA approach is actually faster. A report written in VBA can be run every other second, so it is easy to adjust something such as the column width of a table and to rerun the report to check the output. A html report created with VBA is written out as a html file and the ms-access can issue a shell command to open the report in a web browser. If the browser is already open, the new report opens in a new tab so you can see what the previous version looked like as this version will still be open in another tab.
Write the report in a standard module (not in a form module) and call it from some button-click event on the form. The report should only need to be told what the title is, what the output filename and location are and the data scope that the report should output. The report procedure contains all other logic necessary for creating the report. Below is the calling procedure for triggering a report in one of my applications. The purpose of the calling code is to export a list of geotagged photos in a delimited text file so that I can plot the photo locations on a map. The process for exporting a html file is very similar. Some custom functions are in the code below but the structure should be recognisable.
Private Sub cmdCSV_File_Click()
Dim FolderName As String
Dim FileName As String
Dim ReportTitle As String
Dim SQL As String
Dim FixedFields As String
Dim WhereClause As String
Dim SortOrder As String
'Set destination of exported data
FolderName = InputBox("Please enter name of folder to export to", AppName, mDefaultFolder)
If mPaths.FolderExists(FolderName).Success Then
mDefaultFolder = FolderName 'holds default folder name in case it is needed again
Else
MsgBox "Can't find this folder", vbCritical, AppName
Exit Sub
End If
FileName = CheckTrailingSlash(FolderName) & "PhotoPoints.txt"
'Set Report Title
If Nz(Me.chkAllProjects, 0) Then
ReportTitle = "Photos from all Projects"
ElseIf Nz(Me.SampleID, 0) Then
ReportTitle = "Photos from Sample " & Me.SampleID
ElseIf Nz(Me.SurveyID, 0) Then
ReportTitle = "Photos from Survey " & Me.SurveyID
ElseIf Nz(Me.ProjectID, 0) Then
ReportTitle = "Photos from Project " & Me.ProjectID
Else
MsgBox "Please select a scope before pressing this button", vbExclamation, AppName
Exit Sub
End If
'Update paths to photos
If Have(Me.ProjectID) Then
WhereClause = " (PhotoPath_ProjectID = " & Me.ProjectID & ")" 'also covers sample and survey level selections
Else
WhereClause = " True" 'when all records is selected
End If
Call mPhotos.UpdatePhotoPaths(WhereClause) 'refreshes current paths
'Set fixed parts of SQL statement
FixedFields = "SELECT Photos.*, PhotoPaths.PhotoPath_Alias, PhotoPaths.CurrentPath & Photos.PhotoName AS URL, " _
& "PhotoPaths.CurrentPath & 'Thumbs\' & Photos.PhotoName as Thumb " _
& "FROM Photos INNER JOIN PhotoPaths ON Photos.PhotoPathID = PhotoPaths.PhotoPathID WHERE "
SortOrder = " ORDER BY ProjectID, SurveyID, SampleID, Photo_ID"
'set scope for export
WhereClause = "(((Photos.Latitude) Between -90 And 90) AND ((Photos.Longitude) Between -180 And 180) AND ((Photos.Latitude)<>0) AND ((Photos.Longitude)<>0)) AND " & WhereClause
SQL = FixedFields & WhereClause & SortOrder & ";"
'Export data as a delimited list
FileName = ExportCSV(FileName, SQL)
Call OpenBrowser(FileName)
End Sub
The next bit of code actually writes out the delimited text file (html just has tags instead of pipes). The vertical bar or pipe is used to separate the values rather than a comma in this case as commas may occur in the data. The code works out how many columns there are for itself and puts headings at the top.
Public Function ExportCSV(FileAddress As Variant, SQL As String) As String
If Not gDeveloping Then On Error GoTo procerr
PushStack ("mfiles.ExportCSV")
'Exports a csv file
If Nz(FileAddress, "") = "" Then
ExportCSV = "Failed"
Exit Function
End If
'Create text file:
Dim webfile As Object, w
Set webfile = CreateObject("Scripting.FileSystemObject")
Set w = webfile.CreateTextFile(FileAddress, True)
Dim D As Database, R As Recordset, NumberOfFields As Long, Out As String, i As Long
Set D = CurrentDb()
Set R = D.OpenRecordset(SQL, dbOpenSnapshot)
If R.RecordCount > 0 Then
With R
NumberOfFields = .Fields.Count - 1
'Field headings
For i = 0 To NumberOfFields
If i = 0 Then
Out = .Fields(i).Name
Else
Out = Out & "|" & .Fields(i).Name
End If
Next
w.writeline Out
'Field data
Do Until .EOF
For i = 0 To NumberOfFields
If i = 0 Then
Out = .Fields(i)
Else
Out = Out & "|" & .Fields(i)
End If
Next i
w.writeline Out
.MoveNext
Loop
End With
End If
Set R = Nothing
Set D = Nothing
ExportCSV = FileAddress
exitproc:
PopStack
Exit Function
procerr:
Call NewErrorLog(Err.Number, Err.Description, gCurrentProc, FileAddress & ", " & SQL)
Resume exitproc
End Function
Below is a snippet from the openbrowser function. The rest of the function deals with figuring out where the web browser is, as this varies with the version of windows and whether the browser is 32 or 64 bit.
'Set up preferred browser
If Right(BrowserPath, 9) = "Opera.exe" Then
FilePrefix = "file://localhost/"
ElseIf Right(BrowserPath, 11) = "Firefox.exe" Then
FilePrefix = "file:///"
Else
FilePrefix = ""
End If
'Show report
Instruction = BrowserPath & " " & FilePrefix & WebpageName
TaskSuccessID = Shell(Instruction, vbMaximizedFocus)
This example contains about 90% of the code needed to create a html report that has its scope set by the form that calls it. Hope this gets someone over the hump.
I am using the following code, based on from previous posts and answers by Remou and Anthony Jones.
Dim db: db = "C:\Dokumente und Einstellungen\hom\Anwendungsdaten\BayWotch4\baywotch.db5"
Dim exportDir: exportDir = "C:\Dokumente und Einstellungen\hom\Desktop"
Dim exportFile: exportFile=NewFileName(exportDir)
Dim cn: Set cn = CreateObject("ADODB.Connection")
cn.Open _
"Provider = Microsoft.Jet.OLEDB.4.0; " & _
"Data Source =" & db
cn.Execute "SELECT * INTO [text;HDR=No;Database=" & exportDir & _
";CharacterSet=65001]." & exportFile & " FROM tblAuction"
'Export file
'Support functions
Function NewFileName(ExportPath)
Dim fs
Dim NewFileTemp
Set fs = CreateObject("Scripting.FileSystemObject")
NewFileTemp = "CSV" & Year(Date) _
& Month(Date) & Day(Date) & ".csv"
NewFileName = NewFileTemp
End Function
The problem I am having, is when I export the file, the csv file contains headers, despite HDR being set to No. It will have the names of my columns in quotes before the actual data, which causes problems when attempting to import.
My second problem is that special characters do not seem to be escaped.
I am loading the data into mysql with:
LOAD DATA LOCAL INFILE 'file' INTO TABLE MYTABLE FIELDS TERMINATED BY ';' ENCLOSED BY '"' ESCAPED BY '\\'
I have also tried without the ESCAPED BY clause.
The problem is that one of the fields contains html data, which means quotes, slashes etc. This causes the data to be imported incorrectly, with date fields being inserted into the usernames fields and such. How can I escape to stop this from happening, or import correctly?
I am using a scheme.ini like the following:
[CSV2009427.csv]
ColNameHeader=No
CharacterSet=65001
Format=Delimited(;)
Col1=article_no Char Width 19
And column headers are still exported. Is it not possible to do this in a way without requiring schema.ini? I.e. being able to use the script in a portable way, where a schema.ini may not alway exist?
The problem I am having, is when I
export the file, the csv file contains
headers, despite HDR being set to No.
I think you need to need to include ColNameHeader=False in the Schema.ini File.
Example:
C:\schema.ini
[blah.csv]
ColNameHeader=False
CharacterSet=1252
Format=CSVDelimited
Col1=pence_amount Integer
SQL code:
SELECT * INTO [text;Database=C:\].blah#csv FROM Coins;
Note the schema.ini file is saved in the same directory as specified by Database in the connection string in the SQL.
Result: no headers.