From bf68e4433ca950744045918fcb83a46a16abd284 Mon Sep 17 00:00:00 2001 From: Ansgar Becker Date: Thu, 5 Jul 2007 19:45:18 +0000 Subject: [PATCH] Improvements for CSV import dialog: * Add feature: Read and write all options from / to registry, using some existing CSV-options * Fix bug: Correct escaping for db, table, columns, values for terminator, etc. * Style change: Drop superflous checkboxes from checkbox/edit pairs to save clicks. Checking for empty edits has the same effect. * Style change: Don't convert backslashes in filename to slashes. No need to take care of escaping, esc() does that better. --- source/loaddata.dfm | 122 ++++++++++++++++++------------------------ source/loaddata.pas | 125 +++++++++++++++++++++----------------------- 2 files changed, 112 insertions(+), 135 deletions(-) diff --git a/source/loaddata.dfm b/source/loaddata.dfm index d671b7c7..b967abb8 100644 --- a/source/loaddata.dfm +++ b/source/loaddata.dfm @@ -40,7 +40,7 @@ object loaddataform: Tloaddataform end object lblFields: TLabel Left = 208 - Top = 56 + Top = 58 Width = 30 Height = 13 Caption = 'Fields:' @@ -52,13 +52,12 @@ object loaddataform: Tloaddataform Height = 13 Caption = 'Lines:' end - object lblIgnoreLines: TLabel + object lblIgnoreLinesCount: TLabel Left = 415 Top = 169 Width = 25 Height = 13 Caption = 'Lines' - Enabled = False end object lblColumns: TLabel Left = 16 @@ -84,6 +83,41 @@ object loaddataform: Tloaddataform 'ons > 3.22.6. On previous versions you will get an error!' WordWrap = True end + object lblFieldTerminater: TLabel + Left = 272 + Top = 58 + Width = 63 + Height = 13 + Caption = 'terminated by' + end + object lblFieldEncloser: TLabel + Left = 272 + Top = 83 + Width = 57 + Height = 13 + Caption = 'enclosed by' + end + object lblFieldEscaper: TLabel + Left = 272 + Top = 107 + Width = 55 + Height = 13 + Caption = 'escaped by' + end + object lblLineTerminator: TLabel + Left = 272 + Top = 147 + Width = 63 + Height = 13 + Caption = 'terminated by' + end + object lblIgnoreLines: TLabel + Left = 272 + Top = 170 + Width = 29 + Height = 13 + Caption = 'ignore' + end object btnImport: TButton Left = 328 Top = 312 @@ -150,57 +184,27 @@ object loaddataform: Tloaddataform TabOrder = 5 OnChange = comboTableChange end - object chkFieldsTerminated: TCheckBox - Left = 272 - Top = 56 - Width = 97 - Height = 17 - Caption = 'terminated by' - TabOrder = 6 - OnClick = chkFieldsTerminatedClick - end object editFieldTerminator: TEdit Left = 360 Top = 56 Width = 49 Height = 21 - Enabled = False - TabOrder = 7 + TabOrder = 6 Text = '\t' end - object chkFieldsEnclosed: TCheckBox - Left = 272 - Top = 80 - Width = 97 - Height = 17 - Caption = 'enclosed by' - TabOrder = 8 - OnClick = chkFieldsEnclosedClick - end object editFieldEncloser: TEdit Left = 360 Top = 80 Width = 49 Height = 21 - Enabled = False - TabOrder = 9 - end - object chkFieldsEscaped: TCheckBox - Left = 272 - Top = 104 - Width = 97 - Height = 17 - Caption = 'escaped by' - TabOrder = 10 - OnClick = chkFieldsEscapedClick + TabOrder = 7 end object editFieldEscaper: TEdit Left = 360 Top = 104 Width = 49 Height = 21 - Enabled = False - TabOrder = 11 + TabOrder = 8 Text = '\\' end object chkFieldsEnclosedOptionally: TCheckBox @@ -209,43 +213,23 @@ object loaddataform: Tloaddataform Width = 73 Height = 17 Caption = 'optionally' - Enabled = False - TabOrder = 12 - end - object chkLinesTerminated: TCheckBox - Left = 272 - Top = 144 - Width = 89 - Height = 17 - Caption = 'terminated by' - TabOrder = 13 - OnClick = chkLinesTerminatedClick + TabOrder = 9 end object editLineTerminator: TEdit Left = 360 Top = 144 Width = 49 Height = 21 - Enabled = False - TabOrder = 14 + TabOrder = 10 Text = '\n' end - object chkLinesIgnore: TCheckBox - Left = 272 - Top = 168 - Width = 73 - Height = 17 - Caption = 'ignore' - TabOrder = 15 - OnClick = chkLinesIgnoreClick - end object chklistColumns: TCheckListBox Left = 16 Top = 128 Width = 121 Height = 161 ItemHeight = 13 - TabOrder = 16 + TabOrder = 11 end object comboDatabase: TComboBox Left = 16 @@ -254,7 +238,7 @@ object loaddataform: Tloaddataform Height = 21 Style = csDropDownList ItemHeight = 13 - TabOrder = 17 + TabOrder = 12 OnChange = comboDatabaseChange end object chkReplace: TCheckBox @@ -263,7 +247,7 @@ object loaddataform: Tloaddataform Width = 65 Height = 17 Caption = 'Replace' - TabOrder = 18 + TabOrder = 13 OnClick = chkReplaceClick end object chkIgnore: TCheckBox @@ -272,7 +256,7 @@ object loaddataform: Tloaddataform Width = 57 Height = 17 Caption = 'Ignore' - TabOrder = 19 + TabOrder = 14 OnClick = chkIgnoreClick end object btnColUp: TBitBtn @@ -280,7 +264,7 @@ object loaddataform: Tloaddataform Top = 178 Width = 25 Height = 25 - TabOrder = 21 + TabOrder = 16 OnClick = btnColUpClick Glyph.Data = { F6000000424DF600000000000000760000002800000010000000100000000100 @@ -297,7 +281,7 @@ object loaddataform: Tloaddataform Top = 202 Width = 25 Height = 25 - TabOrder = 20 + TabOrder = 15 OnClick = btnColDownClick Glyph.Data = { F6000000424DF600000000000000760000002800000010000000100000000100 @@ -314,20 +298,18 @@ object loaddataform: Tloaddataform Top = 167 Width = 33 Height = 21 - Enabled = False - TabOrder = 22 + TabOrder = 17 Text = '1' end object updownIgnoreLines: TUpDown - Left = 391 - Top = 168 + Left = 393 + Top = 167 Width = 18 Height = 21 Associate = editIgnoreLines - Enabled = False Max = 32767 Position = 1 - TabOrder = 23 + TabOrder = 18 end object OpenDialogCSVFile: TOpenDialog DefaultExt = 'csv' diff --git a/source/loaddata.pas b/source/loaddata.pas index bc08ab4c..2b377c59 100644 --- a/source/loaddata.pas +++ b/source/loaddata.pas @@ -23,19 +23,14 @@ type lblTable: TLabel; comboTable: TComboBox; lblFilename: TLabel; - chkFieldsTerminated: TCheckBox; lblFields: TLabel; editFieldTerminator: TEdit; - chkFieldsEnclosed: TCheckBox; editFieldEncloser: TEdit; - chkFieldsEscaped: TCheckBox; editFieldEscaper: TEdit; chkFieldsEnclosedOptionally: TCheckBox; lblLines: TLabel; - chkLinesTerminated: TCheckBox; editLineTerminator: TEdit; - chkLinesIgnore: TCheckBox; - lblIgnoreLines: TLabel; + lblIgnoreLinesCount: TLabel; lblColumns: TLabel; chklistColumns: TCheckListBox; comboDatabase: TComboBox; @@ -48,15 +43,15 @@ type btnColDown: TBitBtn; editIgnoreLines: TEdit; updownIgnoreLines: TUpDown; + lblFieldTerminater: TLabel; + lblFieldEncloser: TLabel; + lblFieldEscaper: TLabel; + lblLineTerminator: TLabel; + lblIgnoreLines: TLabel; procedure btnCancelClick(Sender: TObject); procedure FormShow(Sender: TObject); procedure comboDatabaseChange(Sender: TObject); procedure comboTableChange(Sender: TObject); - procedure chkFieldsTerminatedClick(Sender: TObject); - procedure chkFieldsEnclosedClick(Sender: TObject); - procedure chkFieldsEscapedClick(Sender: TObject); - procedure chkLinesTerminatedClick(Sender: TObject); - procedure chkLinesIgnoreClick(Sender: TObject); procedure btnImportClick(Sender: TObject); procedure btnOpenFileClick(Sender: TObject); procedure chkReplaceClick(Sender: TObject); @@ -102,6 +97,7 @@ procedure Tloaddataform.FormShow(Sender: TObject); var tn : TTreeNode; i : Integer; + reg : TRegistry; begin // read dbs and Tables from treeview comboDatabase.Items.Clear; @@ -122,13 +118,29 @@ begin end; comboDatabaseChange(self); - // filename - with TRegistry.Create do - if OpenKey(REGPATH, true) then - editFilename.Text := ReadString('loadfilename'); - if editFilename.Text = '' then - editFilename.Text := ExtractFilePath(paramstr(0)) + 'import.csv'; - editFilename.Text := stringreplace(editFilename.Text, '\', '/', [rfReplaceAll]); + reg := TRegistry.Create; + if reg.OpenKey(REGPATH, true) then + begin + // filename + editFilename.Text := reg.ReadString('loadfilename'); + // Use options from CSV export + editFieldTerminator.Text := reg.ReadString('CSVSeparator'); + editFieldEncloser.Text := reg.ReadString('CSVEncloser'); + editLineTerminator.Text := reg.ReadString('CSVTerminator'); + // Other options + if reg.ValueExists('CSVImportFieldsEnclosedOptionally') then + chkFieldsEnclosedOptionally.Checked := reg.ReadBool('CSVImportFieldsEnclosedOptionally'); + editFieldEscaper.Text := reg.ReadString('CSVImportFieldEscaper'); + if reg.ValueExists('CSVImportIgnoreLines') then + updownIgnoreLines.Position := reg.ReadInteger('CSVImportIgnoreLines'); + if reg.ValueExists('CSVImportLowPriority') then + chkLowPriority.Checked := reg.ReadBool('CSVImportLowPriority'); + if reg.ValueExists('CSVImportReplace') then + chkReplace.Checked := reg.ReadBool('CSVImportReplace'); + if reg.ValueExists('CSVImportIgnore') then + chkIgnore.Checked := reg.ReadBool('CSVImportIgnore'); + end; + end; @@ -174,49 +186,32 @@ begin end; -procedure Tloaddataform.chkFieldsTerminatedClick(Sender: TObject); -begin - editFieldTerminator.Enabled := (sender as TCheckBox).checked; -end; - - -procedure Tloaddataform.chkFieldsEnclosedClick(Sender: TObject); -begin - editFieldEncloser.Enabled := (sender as TCheckBox).checked; - chkFieldsEnclosedOptionally.Enabled := (sender as TCheckBox).checked; -end; - - -procedure Tloaddataform.chkFieldsEscapedClick(Sender: TObject); -begin - editFieldEscaper.Enabled := (sender as TCheckBox).checked; -end; - - -procedure Tloaddataform.chkLinesTerminatedClick(Sender: TObject); -begin - editLineTerminator.Enabled := (sender as TCheckBox).checked; -end; - - -procedure Tloaddataform.chkLinesIgnoreClick(Sender: TObject); -begin - updownIgnoreLines.Enabled := (sender as TCheckBox).checked; - editIgnoreLines.Enabled := (sender as TCheckBox).checked; - lblIgnoreLines.Enabled := (sender as TCheckBox).checked; -end; - - procedure Tloaddataform.btnImportClick(Sender: TObject); var query : string; col : TStringList; i : Integer; + reg : TRegistry; begin - with TRegistry.Create do - if OpenKey(REGPATH, true) then - WriteString('loadfilename', editFilename.Text); + // Save settings + reg := TRegistry.Create; + if reg.OpenKey(REGPATH, true) then + begin + // filename + reg.WriteString( 'loadfilename', editFilename.Text ); + // Use options from CSV export + reg.WriteString( 'CSVSeparator', editFieldTerminator.Text ); + reg.WriteString( 'CSVEncloser', editFieldEncloser.Text ); + reg.WriteString( 'CSVTerminator', editLineTerminator.Text ); + // Other options + reg.WriteBool( 'CSVImportFieldsEnclosedOptionally', chkFieldsEnclosedOptionally.Checked ); + reg.WriteString( 'CSVImportFieldEscaper', editFieldEscaper.Text ); + reg.WriteInteger( 'CSVImportIgnoreLines', updownIgnoreLines.Position ); + reg.WriteBool( 'CSVImportLowPriority', chkLowPriority.Checked ); + reg.WriteBool( 'CSVImportReplace', chkReplace.Checked ); + reg.WriteBool( 'CSVImportIgnore', chkIgnore.Checked ); + end; query := 'LOAD DATA '; @@ -228,33 +223,33 @@ begin query := query + 'REPLACE ' else if chkIgnore.Checked then query := query + 'IGNORE '; - query := query + 'INTO TABLE ' + comboDatabase.Text + '.' + comboTable.Text + ' '; + query := query + 'INTO TABLE ' + Mainform.Mask(comboDatabase.Text) + '.' + Mainform.Mask(comboTable.Text) + ' '; // Fields: - if chkFieldsTerminated.Checked or chkFieldsEnclosed.Checked or chkFieldsEscaped.Checked then + if (editFieldTerminator.Text <> '') or (editFieldEncloser.Text <> '') or (editFieldEscaper.Text <> '') then query := query + 'FIELDS '; - if chkFieldsTerminated.Checked then - query := query + 'TERMINATED BY ''' + editFieldTerminator.Text + ''' '; - if chkFieldsEnclosed.Checked then + if editFieldTerminator.Text <> '' then + query := query + 'TERMINATED BY ' + esc(editFieldTerminator.Text) + ' '; + if editFieldEncloser.Text <> '' then begin if chkFieldsEnclosedOptionally.Checked then query := query + 'OPTIONALLY '; - query := query + 'ENCLOSED BY ''' + editFieldEncloser.Text + ''' '; + query := query + 'ENCLOSED BY ' + esc(editFieldEncloser.Text) + ' '; end; - if chkFieldsEscaped.Checked then - query := query + 'ESCAPED BY ''' + editFieldEscaper.Text + ''' '; + if editFieldEscaper.Text <> '' then + query := query + 'ESCAPED BY ' + esc(editFieldEscaper.Text) + ' '; // Lines: - if chkLinesTerminated.Checked then + if editLineTerminator.Text <> '' then query := query + 'LINES TERMINATED BY ''' + editLineTerminator.Text + ''' '; - if chkLinesIgnore.Checked then + if updownIgnoreLines.Position > 0 then query := query + 'IGNORE ' + inttostr(updownIgnoreLines.Position) + ' LINES '; col := TStringList.Create; for i:=0 to chklistColumns.Items.Count - 1 do begin if chklistColumns.checked[i] then - col.Add(chklistColumns.Items[i]); + col.Add(Mainform.Mask( chklistColumns.Items[i] )); end; // if col.Count < ColumnsCheckListBox.Items.Count then