From b5de17c15df7328d631023ddb9fbf9a51128d91c Mon Sep 17 00:00:00 2001 From: Ansgar Becker Date: Thu, 28 Apr 2016 18:13:47 +0000 Subject: [PATCH] Wrap grid export code in a try/except block, so we can catch a potential "Cannot determine name of table" error, occurring while trying to get the WHERE clause for DELETEs. See http://www.heidisql.com/forum.php?t=21168 --- source/exportgrid.pas | 879 +++++++++++++++++++++--------------------- 1 file changed, 445 insertions(+), 434 deletions(-) diff --git a/source/exportgrid.pas b/source/exportgrid.pas index 4a77fc60..10f800fd 100644 --- a/source/exportgrid.pas +++ b/source/exportgrid.pas @@ -482,475 +482,486 @@ begin Exit; end; - Screen.Cursor := crHourglass; + try + Screen.Cursor := crHourglass; - SelectionOnly := grpSelection.ItemIndex = 0; - Mainform.DataGridEnsureFullRows(Grid, SelectionOnly); - GridData := Mainform.GridResult(Grid); - if SelectionOnly then - NodeCount := Grid.SelectedCount - else - NodeCount := Grid.RootNodeCount; - MainForm.EnableProgress(NodeCount); - TableName := BestTableName(GridData); - ExcludeCol := NoColumn; - if (not chkIncludeAutoIncrement.Checked) or (not chkIncludeAutoIncrement.Enabled) then - ExcludeCol := GridData.AutoIncrementColumn; + SelectionOnly := grpSelection.ItemIndex = 0; + Mainform.DataGridEnsureFullRows(Grid, SelectionOnly); + GridData := Mainform.GridResult(Grid); + if SelectionOnly then + NodeCount := Grid.SelectedCount + else + NodeCount := Grid.RootNodeCount; + MainForm.EnableProgress(NodeCount); + TableName := BestTableName(GridData); + ExcludeCol := NoColumn; + if (not chkIncludeAutoIncrement.Checked) or (not chkIncludeAutoIncrement.Enabled) then + ExcludeCol := GridData.AutoIncrementColumn; - if radioOutputCopyToClipboard.Checked then - Encoding := TEncoding.UTF8 - else begin - Encoding := MainForm.GetEncodingByName(comboEncoding.Text); - // Add selected file to file list, and sort it onto the top of the list - i := FRecentFiles.IndexOf(editFilename.Text); - if i > -1 then - FRecentFiles.Delete(i); - FRecentFiles.Insert(0, editFilename.Text); - for i:=FRecentFiles.Count-1 downto 10 do - FRecentFiles.Delete(i); - end; - S := TStringStream.Create(Header, Encoding); - Header := ''; - case ExportFormat of - efHTML: begin - Header := - '' + CRLF + CRLF + - '' + CRLF + - ' ' + CRLF + - ' ' + TableName + '' + CRLF + - ' ' + CRLF + - ' ' + CRLF + - ' ' + CRLF + - ' ' + CRLF + CRLF + - ' ' + CRLF + CRLF; - if chkIncludeQuery.Checked then - Header := Header + '

' + GridData.SQL + '

' + CRLF + CRLF; - Header := Header + ' ' + CRLF; - if chkIncludeColumnNames.Checked then begin - Header := Header + - ' ' + CRLF + - ' ' + CRLF; - Col := Grid.Header.Columns.GetFirstVisibleColumn; - while Col > NoColumn do begin - if Col <> ExcludeCol then - Header := Header + ' ' + CRLF; - Col := Grid.Header.Columns.GetNextVisibleColumn(Col); - end; - Header := Header + - ' ' + CRLF + - ' ' + CRLF; - end; - Header := Header + - ' ' + CRLF; + if radioOutputCopyToClipboard.Checked then + Encoding := TEncoding.UTF8 + else begin + Encoding := MainForm.GetEncodingByName(comboEncoding.Text); + // Add selected file to file list, and sort it onto the top of the list + i := FRecentFiles.IndexOf(editFilename.Text); + if i > -1 then + FRecentFiles.Delete(i); + FRecentFiles.Insert(0, editFilename.Text); + for i:=FRecentFiles.Count-1 downto 10 do + FRecentFiles.Delete(i); end; - - efExcel, efCSV: begin - Separator := GridData.Connection.UnescapeString(editSeparator.Text); - Encloser := GridData.Connection.UnescapeString(editEncloser.Text); - Terminator := GridData.Connection.UnescapeString(editTerminator.Text); - if chkIncludeColumnNames.Checked then begin - Col := Grid.Header.Columns.GetFirstVisibleColumn; - while Col > NoColumn do begin - // Alter column name in header if data is not raw. - if Col <> ExcludeCol then begin - Data := Grid.Header.Columns[Col].Text; - if (GridData.DataType(Col).Category in [dtcBinary, dtcSpatial]) and (not Mainform.actBlobAsText.Checked) then - Data := 'HEX(' + Data + ')'; - // Add header item. - if Header <> '' then - Header := Header + Separator; - Header := Header + Encloser + Data + Encloser; - end; - Col := Grid.Header.Columns.GetNextVisibleColumn(Col); - end; - Header := Header + Terminator; - end; - end; - - efXML: begin - // Imitate mysqldump's XML style - Header := '' + CRLF + CRLF; - if chkIncludeQuery.Checked then - Header := Header + '' + CRLF - else - Header := Header + '' + CRLF; - end; - - efLaTeX: begin - Header := '\begin{tabular}'; - Separator := ' & '; - Encloser := ''; - Terminator := '\\ '+CRLF; - Header := Header + '{'; - Col := Grid.Header.Columns.GetFirstVisibleColumn; - while Col > NoColumn do begin - if Col <> ExcludeCol then - Header := Header + ' c '; - Col := Grid.Header.Columns.GetNextVisibleColumn(Col); - end; - Header := Header + '}' + CRLF; - if chkIncludeColumnNames.Checked then begin - Col := Grid.Header.Columns.GetFirstVisibleColumn; - while Col > NoColumn do begin - if Col <> ExcludeCol then - Header := Header + Grid.Header.Columns[Col].Text + Separator; - Col := Grid.Header.Columns.GetNextVisibleColumn(Col); - end; - Delete(Header, Length(Header)-Length(Separator)+1, Length(Separator)); - Header := Header + Terminator; - end; - end; - - efWiki: begin - Separator := ' || '; - Encloser := ''; - Terminator := ' ||'+CRLF; - if chkIncludeColumnNames.Checked then begin - Header := '|| '; - Col := Grid.Header.Columns.GetFirstVisibleColumn; - while Col > NoColumn do begin - if Col <> ExcludeCol then - Header := Header + '*' + Grid.Header.Columns[Col].Text + '*' + Separator; - Col := Grid.Header.Columns.GetNextVisibleColumn(Col); - end; - Delete(Header, Length(Header)-Length(Separator)+1, Length(Separator)); - Header := Header + Terminator; - end; - end; - - efPHPArray: begin - if radioOutputFile.Checked then - Header := ' NoColumn do begin - if Col <> ExcludeCol then begin - if chkIncludeColumnNames.Checked then - Header := Header + Grid.Header.Columns[Col].Text + Separator - else - Header := Header + Separator - end; - Col := Grid.Header.Columns.GetNextVisibleColumn(Col); - end; - Header := Header + Terminator; - // Write an extra line with dashes below the heading, otherwise the table won't parse - Header := Header + TrimLeft(Separator); - Col := Grid.Header.Columns.GetFirstVisibleColumn; - while Col > NoColumn do begin - if Col <> ExcludeCol then begin - Header := Header + '-'; - if GridData.DataType(Col).Category in [dtcInteger, dtcReal] then - Header := Header + ':'; - Header := Header + Separator; - end; - Col := Grid.Header.Columns.GetNextVisibleColumn(Col); - end; - Header := Header + Terminator; - end; - - efJSON: begin - // JavaScript Object Notation - Header := '{' + CRLF; - if chkIncludeQuery.Checked then - Header := Header + #9 + '"query": "'+HTMLSpecialChars(GridData.SQL)+'",' + CRLF - else - Header := Header + #9 + '"table": "'+HTMLSpecialChars(TableName)+'",' + CRLF ; - Header := Header + #9 + '"rows":' + CRLF + #9 + '['; - end; - - end; - S.WriteString(Header); - - Node := GetNextNode(Grid, nil, SelectionOnly); - while Assigned(Node) do begin - // Update status once in a while. - if (Node.Index+1) mod 100 = 0 then begin - MainForm.ShowStatusMsg(f_('Exporting row %s of %s (%d%%, %s)', - [FormatNumber(Node.Index+1), - FormatNumber(NodeCount), - Trunc((Node.Index+1) / NodeCount *100), - FormatByteNumber(S.Size)] - )); - MainForm.ProgressStep; - end; - RowNum := Grid.GetNodeData(Node); - GridData.RecNo := RowNum^; - - // Row preamble + S := TStringStream.Create(Header, Encoding); + Header := ''; case ExportFormat of - efHTML: tmp := ' ' + CRLF; - - efXML: tmp := #9'' + CRLF; - - efSQLInsert, efSQLReplace, efSQLDeleteInsert: begin - tmp := ''; - if ExportFormat = efSQLDeleteInsert then begin - tmp := tmp + 'DELETE FROM ' + GridData.Connection.QuoteIdent(Tablename) + ' WHERE' + GridData.GetWhereClause + ';' + CRLF; + efHTML: begin + Header := + '' + CRLF + CRLF + + '' + CRLF + + ' ' + CRLF + + ' ' + TableName + '' + CRLF + + ' ' + CRLF + + ' ' + CRLF + + ' ' + CRLF + + ' ' + CRLF + CRLF + + ' ' + CRLF + CRLF; + if chkIncludeQuery.Checked then + Header := Header + '

' + GridData.SQL + '

' + CRLF + CRLF; + Header := Header + '
' + Grid.Header.Columns[Col].Text + '
' + CRLF; if chkIncludeColumnNames.Checked then begin - tmp := tmp + ' ('; + Header := Header + + ' ' + CRLF + + ' ' + CRLF; Col := Grid.Header.Columns.GetFirstVisibleColumn; while Col > NoColumn do begin if Col <> ExcludeCol then - tmp := tmp + GridData.Connection.QuoteIdent(Grid.Header.Columns[Col].Text)+', '; + Header := Header + ' ' + CRLF; Col := Grid.Header.Columns.GetNextVisibleColumn(Col); end; - Delete(tmp, Length(tmp)-1, 2); - tmp := tmp + ')'; + Header := Header + + ' ' + CRLF + + ' ' + CRLF; end; - tmp := tmp + ' VALUES ('; + Header := Header + + ' ' + CRLF; end; - efWiki: tmp := TrimLeft(Separator); - - efPHPArray: tmp := #9 + 'array( // row #'+FormatNumber(GridData.RecNo)+CRLF; - - efMarkDown: tmp := '| '; - - efJSON: begin - if chkIncludeColumnNames.Checked then - tmp := CRLF + #9#9 + '{' + CRLF - else - tmp := CRLF + #9#9 + '[' + CRLF - end - - else tmp := ''; - end; - - Col := Grid.Header.Columns.GetFirstVisibleColumn; - while Col > NoColumn do begin - if Col <> ExcludeCol then begin - if (GridData.DataType(Col).Category in [dtcBinary, dtcSpatial]) and (not Mainform.actBlobAsText.Checked) then - Data := GridData.HexValue(Col) - else - Data := GridData.Col(Col); - // Keep formatted numeric values - if (GridData.DataType(Col).Category in [dtcInteger, dtcReal]) - and (ExportFormat in [efExcel, efHTML, efMarkDown]) then - Data := FormatNumber(Data, False); - - case ExportFormat of - efHTML: begin - // Escape HTML control characters in data. - Data := HTMLSpecialChars(Data); - tmp := tmp + ' ' + CRLF; - end; - - efExcel, efCSV, efLaTeX, efWiki, efMarkDown: begin - // Escape encloser characters inside data per de-facto CSV. - Data := StringReplace(Data, Encloser, Encloser+Encloser, [rfReplaceAll]); - if GridData.IsNull(Col) and (ExportFormat in [efExcel, efCSV, efMarkDown]) then - Data := editNull.Text - else - Data := Encloser + Data + Encloser; - tmp := tmp + Data + Separator; - end; - - efXML: begin - // Print cell start tag. - tmp := tmp + #9#9'' + CRLF - else begin + efExcel, efCSV: begin + Separator := GridData.Connection.UnescapeString(editSeparator.Text); + Encloser := GridData.Connection.UnescapeString(editEncloser.Text); + Terminator := GridData.Connection.UnescapeString(editTerminator.Text); + if chkIncludeColumnNames.Checked then begin + Col := Grid.Header.Columns.GetFirstVisibleColumn; + while Col > NoColumn do begin + // Alter column name in header if data is not raw. + if Col <> ExcludeCol then begin + Data := Grid.Header.Columns[Col].Text; if (GridData.DataType(Col).Category in [dtcBinary, dtcSpatial]) and (not Mainform.actBlobAsText.Checked) then - tmp := tmp + ' format="hex"'; - tmp := tmp + '>' + HTMLSpecialChars(Data) + '' + CRLF; + Data := 'HEX(' + Data + ')'; + // Add header item. + if Header <> '' then + Header := Header + Separator; + Header := Header + Encloser + Data + Encloser; end; + Col := Grid.Header.Columns.GetNextVisibleColumn(Col); end; - - efSQLInsert, efSQLReplace, efSQLDeleteInsert: begin - if GridData.IsNull(Col) then - Data := 'NULL' - else if (GridData.DataType(Col).Index = dtBit) and GridData.Connection.Parameters.IsMySQL then - Data := 'b' + esc(Data) - else if (GridData.DataType(Col).Category in [dtcText, dtcTemporal, dtcOther]) - or ((GridData.DataType(Col).Category in [dtcBinary, dtcSpatial]) and Mainform.actBlobAsText.Checked) - then - Data := esc(Data) - else if Data = '' then - Data := esc(Data); - tmp := tmp + Data + ', '; - end; - - efPHPArray: begin - if GridData.IsNull(Col) then - Data := 'NULL' - else case GridData.DataType(Col).Category of - dtcInteger, dtcReal: begin - // Remove zeropadding to avoid octal => integer conversion in PHP - Data := FormatNumber(Data); - Data := UnformatNumber(Data); - end; - else - Data := EscapePHP(Data); - end; - - if chkIncludeColumnNames.Checked then - tmp := tmp + #9#9 + EscapePHP(Grid.Header.Columns[Col].Text) + ' => ' + Data + ','+CRLF - else - tmp := tmp + #9#9 + Data + ','+CRLF; - end; - - efJSON: begin - tmp := tmp + #9#9#9; - if chkIncludeColumnNames.Checked then - tmp := tmp + '"'+HTMLSpecialChars(Grid.Header.Columns[Col].Text) + '": '; - if GridData.IsNull(Col) then - tmp := tmp + 'null,' +CRLF - else begin - case GridData.DataType(Col).Category of - dtcInteger, dtcReal: - tmp := tmp + data; - dtcBinary, dtcSpatial: - tmp := tmp + '"' + Data + '"'; - else - tmp := tmp + '"' + HTMLSpecialChars(Data) + '"' - end; - tmp := tmp + ',' + CRLF; - end; - end; - + Header := Header + Terminator; end; end; - Col := Grid.Header.Columns.GetNextVisibleColumn(Col); + efXML: begin + // Imitate mysqldump's XML style + Header := '' + CRLF + CRLF; + if chkIncludeQuery.Checked then + Header := Header + '' + CRLF + else + Header := Header + '' + CRLF; + end; + + efLaTeX: begin + Header := '\begin{tabular}'; + Separator := ' & '; + Encloser := ''; + Terminator := '\\ '+CRLF; + Header := Header + '{'; + Col := Grid.Header.Columns.GetFirstVisibleColumn; + while Col > NoColumn do begin + if Col <> ExcludeCol then + Header := Header + ' c '; + Col := Grid.Header.Columns.GetNextVisibleColumn(Col); + end; + Header := Header + '}' + CRLF; + if chkIncludeColumnNames.Checked then begin + Col := Grid.Header.Columns.GetFirstVisibleColumn; + while Col > NoColumn do begin + if Col <> ExcludeCol then + Header := Header + Grid.Header.Columns[Col].Text + Separator; + Col := Grid.Header.Columns.GetNextVisibleColumn(Col); + end; + Delete(Header, Length(Header)-Length(Separator)+1, Length(Separator)); + Header := Header + Terminator; + end; + end; + + efWiki: begin + Separator := ' || '; + Encloser := ''; + Terminator := ' ||'+CRLF; + if chkIncludeColumnNames.Checked then begin + Header := '|| '; + Col := Grid.Header.Columns.GetFirstVisibleColumn; + while Col > NoColumn do begin + if Col <> ExcludeCol then + Header := Header + '*' + Grid.Header.Columns[Col].Text + '*' + Separator; + Col := Grid.Header.Columns.GetNextVisibleColumn(Col); + end; + Delete(Header, Length(Header)-Length(Separator)+1, Length(Separator)); + Header := Header + Terminator; + end; + end; + + efPHPArray: begin + if radioOutputFile.Checked then + Header := ' NoColumn do begin + if Col <> ExcludeCol then begin + if chkIncludeColumnNames.Checked then + Header := Header + Grid.Header.Columns[Col].Text + Separator + else + Header := Header + Separator + end; + Col := Grid.Header.Columns.GetNextVisibleColumn(Col); + end; + Header := Header + Terminator; + // Write an extra line with dashes below the heading, otherwise the table won't parse + Header := Header + TrimLeft(Separator); + Col := Grid.Header.Columns.GetFirstVisibleColumn; + while Col > NoColumn do begin + if Col <> ExcludeCol then begin + Header := Header + '-'; + if GridData.DataType(Col).Category in [dtcInteger, dtcReal] then + Header := Header + ':'; + Header := Header + Separator; + end; + Col := Grid.Header.Columns.GetNextVisibleColumn(Col); + end; + Header := Header + Terminator; + end; + + efJSON: begin + // JavaScript Object Notation + Header := '{' + CRLF; + if chkIncludeQuery.Checked then + Header := Header + #9 + '"query": "'+HTMLSpecialChars(GridData.SQL)+'",' + CRLF + else + Header := Header + #9 + '"table": "'+HTMLSpecialChars(TableName)+'",' + CRLF ; + Header := Header + #9 + '"rows":' + CRLF + #9 + '['; + end; + + end; + S.WriteString(Header); + + Node := GetNextNode(Grid, nil, SelectionOnly); + while Assigned(Node) do begin + // Update status once in a while. + if (Node.Index+1) mod 100 = 0 then begin + MainForm.ShowStatusMsg(f_('Exporting row %s of %s (%d%%, %s)', + [FormatNumber(Node.Index+1), + FormatNumber(NodeCount), + Trunc((Node.Index+1) / NodeCount *100), + FormatByteNumber(S.Size)] + )); + MainForm.ProgressStep; + end; + RowNum := Grid.GetNodeData(Node); + GridData.RecNo := RowNum^; + + // Row preamble + case ExportFormat of + efHTML: tmp := ' ' + CRLF; + + efXML: tmp := #9'' + CRLF; + + efSQLInsert, efSQLReplace, efSQLDeleteInsert: begin + tmp := ''; + if ExportFormat = efSQLDeleteInsert then begin + tmp := tmp + 'DELETE FROM ' + GridData.Connection.QuoteIdent(Tablename) + ' WHERE' + GridData.GetWhereClause + ';' + CRLF; + end; + + if ExportFormat in [efSQLInsert, efSQLDeleteInsert] then + tmp := tmp + 'INSERT' + else + tmp := tmp + 'REPLACE'; + tmp := tmp + ' INTO '+GridData.Connection.QuoteIdent(Tablename); + if chkIncludeColumnNames.Checked then begin + tmp := tmp + ' ('; + Col := Grid.Header.Columns.GetFirstVisibleColumn; + while Col > NoColumn do begin + if Col <> ExcludeCol then + tmp := tmp + GridData.Connection.QuoteIdent(Grid.Header.Columns[Col].Text)+', '; + Col := Grid.Header.Columns.GetNextVisibleColumn(Col); + end; + Delete(tmp, Length(tmp)-1, 2); + tmp := tmp + ')'; + end; + tmp := tmp + ' VALUES ('; + end; + + efWiki: tmp := TrimLeft(Separator); + + efPHPArray: tmp := #9 + 'array( // row #'+FormatNumber(GridData.RecNo)+CRLF; + + efMarkDown: tmp := '| '; + + efJSON: begin + if chkIncludeColumnNames.Checked then + tmp := CRLF + #9#9 + '{' + CRLF + else + tmp := CRLF + #9#9 + '[' + CRLF + end + + else tmp := ''; + end; + + Col := Grid.Header.Columns.GetFirstVisibleColumn; + while Col > NoColumn do begin + if Col <> ExcludeCol then begin + if (GridData.DataType(Col).Category in [dtcBinary, dtcSpatial]) and (not Mainform.actBlobAsText.Checked) then + Data := GridData.HexValue(Col) + else + Data := GridData.Col(Col); + // Keep formatted numeric values + if (GridData.DataType(Col).Category in [dtcInteger, dtcReal]) + and (ExportFormat in [efExcel, efHTML, efMarkDown]) then + Data := FormatNumber(Data, False); + + case ExportFormat of + efHTML: begin + // Escape HTML control characters in data. + Data := HTMLSpecialChars(Data); + tmp := tmp + ' ' + CRLF; + end; + + efExcel, efCSV, efLaTeX, efWiki, efMarkDown: begin + // Escape encloser characters inside data per de-facto CSV. + Data := StringReplace(Data, Encloser, Encloser+Encloser, [rfReplaceAll]); + if GridData.IsNull(Col) and (ExportFormat in [efExcel, efCSV, efMarkDown]) then + Data := editNull.Text + else + Data := Encloser + Data + Encloser; + tmp := tmp + Data + Separator; + end; + + efXML: begin + // Print cell start tag. + tmp := tmp + #9#9'' + CRLF + else begin + if (GridData.DataType(Col).Category in [dtcBinary, dtcSpatial]) and (not Mainform.actBlobAsText.Checked) then + tmp := tmp + ' format="hex"'; + tmp := tmp + '>' + HTMLSpecialChars(Data) + '' + CRLF; + end; + end; + + efSQLInsert, efSQLReplace, efSQLDeleteInsert: begin + if GridData.IsNull(Col) then + Data := 'NULL' + else if (GridData.DataType(Col).Index = dtBit) and GridData.Connection.Parameters.IsMySQL then + Data := 'b' + esc(Data) + else if (GridData.DataType(Col).Category in [dtcText, dtcTemporal, dtcOther]) + or ((GridData.DataType(Col).Category in [dtcBinary, dtcSpatial]) and Mainform.actBlobAsText.Checked) + then + Data := esc(Data) + else if Data = '' then + Data := esc(Data); + tmp := tmp + Data + ', '; + end; + + efPHPArray: begin + if GridData.IsNull(Col) then + Data := 'NULL' + else case GridData.DataType(Col).Category of + dtcInteger, dtcReal: begin + // Remove zeropadding to avoid octal => integer conversion in PHP + Data := FormatNumber(Data); + Data := UnformatNumber(Data); + end; + else + Data := EscapePHP(Data); + end; + + if chkIncludeColumnNames.Checked then + tmp := tmp + #9#9 + EscapePHP(Grid.Header.Columns[Col].Text) + ' => ' + Data + ','+CRLF + else + tmp := tmp + #9#9 + Data + ','+CRLF; + end; + + efJSON: begin + tmp := tmp + #9#9#9; + if chkIncludeColumnNames.Checked then + tmp := tmp + '"'+HTMLSpecialChars(Grid.Header.Columns[Col].Text) + '": '; + if GridData.IsNull(Col) then + tmp := tmp + 'null,' +CRLF + else begin + case GridData.DataType(Col).Category of + dtcInteger, dtcReal: + tmp := tmp + data; + dtcBinary, dtcSpatial: + tmp := tmp + '"' + Data + '"'; + else + tmp := tmp + '"' + HTMLSpecialChars(Data) + '"' + end; + tmp := tmp + ',' + CRLF; + end; + end; + + end; + end; + + Col := Grid.Header.Columns.GetNextVisibleColumn(Col); + end; + + // Row epilogue + case ExportFormat of + efHTML: + tmp := tmp + ' ' + CRLF; + efExcel, efCSV, efLaTeX, efWiki: begin + Delete(tmp, Length(tmp)-Length(Separator)+1, Length(Separator)); + tmp := tmp + Terminator; + end; + efXML: + tmp := tmp + #9'' + CRLF; + efSQLInsert, efSQLReplace, efSQLDeleteInsert: begin + Delete(tmp, Length(tmp)-1, 2); + tmp := tmp + ');' + CRLF; + end; + efPHPArray: + tmp := tmp + #9 + '),' + CRLF; + efMarkDown: + tmp := tmp + Terminator; + efJSON: begin + Delete(tmp, length(tmp)-2,2); + if chkIncludeColumnNames.Checked then + tmp := tmp + #9#9 + '},' + else + tmp := tmp + #9#9 + '],'; + end; + end; + S.WriteString(tmp); + + Node := GetNextNode(Grid, Node, SelectionOnly); end; - // Row epilogue + // Footer case ExportFormat of - efHTML: - tmp := tmp + ' ' + CRLF; - efExcel, efCSV, efLaTeX, efWiki: begin - Delete(tmp, Length(tmp)-Length(Separator)+1, Length(Separator)); - tmp := tmp + Terminator; + efHTML: begin + tmp := + ' ' + CRLF + + '
' + Grid.Header.Columns[Col].Text + '
' + Data + '
' + Data + '
' + CRLF + CRLF + + '

' + CRLF + + ' generated ' + DateToStr(now) + ' ' + TimeToStr(now) + + ' by ' + APPNAME + ' ' + Mainform.AppVersion + '' + CRLF + + '

' + CRLF + CRLF + + ' ' + CRLF + + '' + CRLF; end; - efXML: - tmp := tmp + #9'' + CRLF; - efSQLInsert, efSQLReplace, efSQLDeleteInsert: begin - Delete(tmp, Length(tmp)-1, 2); - tmp := tmp + ');' + CRLF; - end; - efPHPArray: - tmp := tmp + #9 + '),' + CRLF; - efMarkDown: - tmp := tmp + Terminator; - efJSON: begin - Delete(tmp, length(tmp)-2,2); - if chkIncludeColumnNames.Checked then - tmp := tmp + #9#9 + '},' + efXML: begin + if chkIncludeQuery.Checked then + tmp := '' + CRLF else - tmp := tmp + #9#9 + '],'; + tmp := '' + CRLF; end; + efLaTeX: + tmp := '\end{tabular}' + CRLF; + efPHPArray: begin + tmp := ');' + CRLF; + if radioOutputFile.Checked then + tmp := tmp + '?>'; + end; + efJSON: begin + S.Size := S.Size - 1; + tmp := CRLF + #9 + ']' + CRLF + '}'; + end; + else + tmp := ''; end; S.WriteString(tmp); - Node := GetNextNode(Grid, Node, SelectionOnly); - end; - - // Footer - case ExportFormat of - efHTML: begin - tmp := - ' ' + CRLF + - ' ' + CRLF + CRLF + - '

' + CRLF + - ' generated ' + DateToStr(now) + ' ' + TimeToStr(now) + - ' by ' + APPNAME + ' ' + Mainform.AppVersion + '' + CRLF + - '

' + CRLF + CRLF + - ' ' + CRLF + - '' + CRLF; - end; - efXML: begin - if chkIncludeQuery.Checked then - tmp := '' + CRLF - else - tmp := '' + CRLF; - end; - efLaTeX: - tmp := '\end{tabular}' + CRLF; - efPHPArray: begin - tmp := ');' + CRLF; - if radioOutputFile.Checked then - tmp := tmp + '?>'; - end; - efJSON: begin - S.Size := S.Size - 1; - tmp := CRLF + #9 + ']' + CRLF + '}'; - end; - else - tmp := ''; - end; - S.WriteString(tmp); - - if radioOutputCopyToClipboard.Checked then begin - HTML := nil; - // SynEdit's exporter is slow on large strings, see issue #2903 - if S.Size < 100*SIZE_KB then begin - case ExportFormat of - efSQLInsert, efSQLReplace, efSQLDeleteInsert: begin - Exporter := TSynExporterHTML.Create(Self); - Exporter.Highlighter := MainForm.SynSQLSyn1; - Exporter.ExportAll(Explode(CRLF, S.DataString)); - HTML := TMemoryStream.Create; - Exporter.SaveToStream(HTML); - Exporter.Free; + if radioOutputCopyToClipboard.Checked then begin + HTML := nil; + // SynEdit's exporter is slow on large strings, see issue #2903 + if S.Size < 100*SIZE_KB then begin + case ExportFormat of + efSQLInsert, efSQLReplace, efSQLDeleteInsert: begin + Exporter := TSynExporterHTML.Create(Self); + Exporter.Highlighter := MainForm.SynSQLSyn1; + Exporter.ExportAll(Explode(CRLF, S.DataString)); + HTML := TMemoryStream.Create; + Exporter.SaveToStream(HTML); + Exporter.Free; + end; + efHTML: HTML := S; + end; + end; + StreamToClipboard(S, HTML, (ExportFormat=efHTML) and (HTML <> nil)); + end else begin + try + S.SaveToFile(Filename); + except + on E:EFCreateError do begin + // Keep form open if file cannot be created + ModalResult := mrNone; + MainForm.SetProgressState(pbsError); + ErrorDialog(E.Message); end; - efHTML: HTML := S; - end; - end; - StreamToClipboard(S, HTML, (ExportFormat=efHTML) and (HTML <> nil)); - end else begin - try - S.SaveToFile(Filename); - except - on E:EFCreateError do begin - // Keep form open if file cannot be created - ModalResult := mrNone; - MainForm.SetProgressState(pbsError); - ErrorDialog(E.Message); end; end; + Mainform.ShowStatusMsg(_('Freeing data...')); + FreeAndNil(S); + + except + // Whole export code wrapped here + on E:EDatabaseError do begin + Screen.Cursor := crDefault; + ErrorDialog(E.Message); + end + else + raise; end; Mainform.DisableProgress; - Mainform.ShowStatusMsg(_('Freeing data...')); - FreeAndNil(S); Mainform.ShowStatusMsg; Screen.Cursor := crDefault; end;