This example is to use how to import a text data into the export control for some simple modifications.
◆ Program function
Go to the partial data in the library's ISO file into the Oracle8 database.
◆ Design requirements
1. Display the import progress bar.
2. During the import process, if a record imports fail, no abnormality is displayed, and the imported record logs will be imported into the log.
◆ Design ideas
The key to the program is separated by the text data field. The usual practice is to process the string, and then compare each character in the string (can be a space, comma, etc.), which will not be the character of the splitter to a string (GetRecordItem) Get the content of a field. With a loop (the number of cycles is determined by GetItemnum), you can divide a string into several fields. The final job is to add the separated data pair to the database.
According to the above ideas, use the existing functions and processes provided by Delphi, it should be is not difficult, but the problem is, I don't want each text to import the program, I will redefine this one. The function process is redefined. Hey, the most annoying is the job of repetitiveness. So there is no ready-made control encapsulate the above process? PS: Don't you use me?
The answer is yes! I just got a free control TPGCSV a few days ago, it is said that the introduction and export of text can be achieved. After turning out, I just I want.
Before going deep into the following, it is necessary to understand the class declaration part of the control.
(Simplus by the author khashayar sadjadi (khashi@pragena.8m.com):
// Chinese part is the notes made by the author
//note:
/ / In this control, Export represents text data into the database, and the import representative is exported from the database to the text. ??? How is it to understand?
// Import the export concept just right :)
Type
// When processing an exception, you can choose to continue or abort
TPGCSVERRRESPONSE = (pgcsvabort, pgcsvignore);
// Process monitoring event declaration, you can transfer the progress of the import / export as a parameter
TPGCSVPROGRESSEVENT = Procedure (Sender: Tobject; Aprogress: longint; var stopit: boolean) of object;
// Event processing declaration when an abnormality occurs, and exception information passes the programmer through the interface.
TPGCSVEXPORTERROREVENT = Procedure (sender: Tobject; Mess: string; recno: longint; var response: tpgcsverrorResponse) of object;
TPGCSV = Class (Tcomponent)
Private
FDataSet: TDataSet;
FCSVMAP,
FCSVFile,
FdateFormat,
FIGNORESTR: STRING;
FSeprator,
FDELIMITER,
Ffieldindicator: char;
Fautoopen,
Fusedelimiter,
Fsilentexport,
FTRIMDATA,
FSTOP,
FemptyTable: boolean;
FbeforeOpen,
FafterOpen,
Fbeforeclosetable,
FafterCloseetable,
FbeforeemptyTable,
FafteEmptyTable,
FbeforeeExport,
Fafterexport,
FbeforeImport,
FAFTERIMPORT,
Fonaddrecord: tnotifyevent;
FEXPORTPROGRESS,
FIMPORTPROGRESS: TPGCSVPROGRESSEVENT;
FEXPORTERROR: TPGCSVEXPORTERROREVENT; FMAPITEMS,
FDEFAULTINT: Integer;
FBUFFERSIZE: longint;
Ffieldcache: TLIST;
protected
FFile: TextFile;
// The following is part of what I want to package
Function CountMapItems: Integer; // Calculate the number of fields of the mapping string
Function GetMapItem (ItemIndex: Integer; VAR Afield: Boolean): String; // Extract the field of the mapping string
Function getCSVRecordItem (ItemIndex: Integer; csvrecord: string): String; // Extract a field in the CSV file string
Function buildmap: String; // Automatically create a mapping, if the CSVMAP column is empty, it will generate a mapping string.
Function ExtractWord (Item: Integer; s, WordDelim: String): String; // Extract a piece of text data string / mapping string
Function WordCount (Const S, WordDelim: String): Integer; // Calculate the number of fields in the text data string / mapping string
Function WordPosition (item: integer; const S, substr: string): Integer; // Calculate the location of sub-string in the string
public
Constructor Create (Aowner: Tcomponent); OVERRIDE;
Published
// Properties
Property DataSet: TDataSet Read FDataSet Write FDataSet;
/ / Set the target dataset to import or export.
Property CSVMap: String Read Fcsvmap Write Fcsvmap;
/ / CSV text data file to the database field value mapping string. The control is determined by this mapping which data is imported and to import which field.
Property CSVFile: String Read Fcsvfile Write Fcsvfile;
// CSV file format, actually the text data file. What does CSV mean? Oh, I don't know.
Property Seprator: Char Read FSeprator Write FSeprator;
// Separator, can be space, or,,;, #, etc. symbol
Property Fieldindicator: Char Read Ffieldindicator; Ffieldindicator;
// field identifier.
Property Autoopen: Boolean Read Fautoopen Write Fautoopen;
// Set AutoOpen to True You can automatically open the data table to import before processing the data and automatically turn off it after the operation is completed.
Property IgnoreString: String Read Fignorestr Write FignoRestr;
// Ignore the recorded identity string.
//for example
// ignoreString: = '(ignore)'; // csvmap: = '$ Name, (ignore), $ AGE'
/ / In this case, the CSVTodataSet method, that is, the import data method will ignore the fields of the second column in the text file.
Property Delimiter: Char Read FDELIMITER WRITE FDELIMITER;
/ / In some CSV documents identifies the identifier of the string record, such as "John", "Boy", 12 ", in this case, TPGCSV
// Ignore these identifiers.
Property EmptyTable: Boolean Read FemptyTable Write femptytable;
// Only valid from the DataseTtocsv method, the role is to create a new CSV file.
Property Usedelimiter: Boolean Read Fusedelimiter Write Fusedelimiter;
// Is there a delimiter.
Property Silentexport: Boolean Read Fsilentexport Write Fsilentexport;
// If this property is True, the application will not display an exception of data operation, and pass the exception information to the programmer through an interface.
Property DateFormat: String Read FdateFormat Write FdateFormat;
// Set the format of the date data in the CSV file.
Property Trimdata: Boolean Read FTrimdata Write FTRIMDATA;
// Whether to remove the space of the data head.
Property Defaultint: Integer Read FDefaultint Write Fdefault;
// The default value of the whole / solid data conversion error
Property Buffersize: Longint Read FBuffersize Write FBuffersize;
// CSV file buffer value, in bytes, speeds of importing and exporting data can be accelerated.
// Events
Property BeforeOpenTable: TNotifyEvent Read FbeforeoPentable Write FbeforeoPENTABLE;
Property instinetable: TNotifyEvent Read Fafteropentable Write FafterOpen;
Property BeforecloSetable: TnotifyEvent Read FbeforecloseclosecloseTable Write Fbeforeclosetable
Property AftercloSetable: TNOTIFYEVENT Read FaftercloSetable Write FafterCloseTable;
Property BeforeemptyTable: TNotifyEvent Read FbeforeemptyTable Write FbeforeemptyTable;
Property Afteremptytable: TNotifyEvent Read FafteTyTable Write FafteremptyTable; Property Beforeimport: TnotifyEvent Read Fbeforeimport Write FbeforeImport
Property AfterImport: TNotifyEvent Read FafterImport Write FafterImport;
Property BeforeExport: TNotifyEvent Read FbeforeExport Write FbeforeExport;
Property Afterexport: TNOTIFYEVENT Read Fafterexport Write Fafterexport;
Property ExportProgress: TPGCSVProgressEvent ReadFexportProgress Write fexportProgress
// Process monitoring event. This event is triggered each time the import of a text data is completed.
Property ImportProgress: TPGCSVProgressEvent Read FIMPORTPROGRESS WRITE FIMPORTPROGRESS
Property OnaddRecord: TNotifyEvent Read FonaddRecord Write FonaddRecord;
Property ExportError: TPGCSVEXPORTERROREVENT ReadFexportError WRITE FEXPORTERROR;
// When an exception occurs, the event is handled, and the exception information passes the programmer through the interface.
//Methodes
// Core content of the entire control
Procedure csvtodataset; // Import text to data set
Procedure datasettocsv; // Method for importing data into the text
END;
PROCEDURE register;
{slightly}
IMPLEMENTATION
{slightly}
End.
From the declaration section we can see that the TPGCSV exports all the import of text data into two ways to CSVTodataSet and DataSetTocsv (text data export). Developers can directly import text files directly in the design phase / Out of the database is connected, then call these two methods in the program run, it is quite convenient to make anything that functions.
Then can I use it directly? There is a problem here.
---- Question 1 and Solutions
In Demo, which comes with this control, the text data file used, the format is as follows
Test.csv
"11", "12", "13", "14"
"21", "22", "23", "24"
"31", "32", "33", "34"
...
And the data format (part) in the ISO file is
SM01632.ISO
... A7507310175B Special Decoration D ¥ 1893 "-1 A Mao Zedong Treasure Collection (Shang, Book) F CPC Central Document Research Room compiled - C" D011200 "...
... A7119029193B Paperback D ¥ 20 "-1 A China: Join the WTO and Economic Reform F Wang Meng Quitic - C Foreign D011200" - ...
We see that records in SM01632.iso files are irregular compared to Test.csv.
What we need is this record
SM01632.ISO
... 7507310175, special fine, 1893, 1, Mao Zedong treasure collection (upper, book), the Central Committee of the Communist Party of China, China Dian, 011200 ...
... 7119029193, Pinback, 20, 1, China: Joining the WTO and Economic Reform, Wang Mengkui, Foreign, 011200- ...
Can the TPGCSV automatically processes this situation? Wow, this universal control seems to be unlikely! (In fact, it is not required) Since it is directly imported with TPGCSV processing, we need to import the record into the database from each record. They are processed by programs, and then the TPGCSV is handed over. How to deal with it here. What we care is that there is a TPGCSV to open such a handled interface?
Let's take a look at the implementation code of the DataSetTocsv method (mainly the notes part):
Procedure tpgcsv.csvtodataset;
VAR
RECORDSTRING,
Temp: String;
i: integer;
C: longint;
D: boolean;
F: REAL;
ErrorResponse: tpgcsverrorResponse;
Buffer: Pointer;
Begin
// Create Field Cache
Ffieldcache: = tlist.create;
// Initiate Map Items
FMapItems: = 0;
// Allocate Buffer Size
GetMem (buffer, fbuffersize);
// Assign and Open CSV file
Assignfile (ffile, fcsvfile);
SetTextBuf (ffile, buffer ^, fbuffersize);
RESET (FFILE);
// Open Table if Nessecary
IF Fautoopen Then
Begin
If Assigned (Fbeforeopentable) THEN
FbeforeOpenTable (Self);
FDataSet.Open;
If Assigned (Fafteropentable) THEN
FAFTEROPENTABLE (Self);
END;
// export to Table from CSV file
If Assigned (FbeforeeExport) THEN
FbeforeeExport (Self);
// set the counter to zero
C: = 0;
Temp: = shortdateFormat;
ShortdateFormat: = fdateFormat;
{************************ The following is the core code part of the text data import, which is also part of the part I want to care. ******** ******************}
FDataSet.disableControls;
While (Not Eof (FSTOP) DO
Begin
// read from CSV
Readln (FFile, Recordstring);
// Note that this seems to be a little bit?
// Add New Record
Try
FDataSet.Append;
For i: = 1 to CountMapItems DO
IF Uppercase (GetMapItem (i, d)) <> Uppercase (FIGNORESTR) THEN
Case FDataSet.fieldByname (GetMapItem (i, d)). DataType Offtinteger:
FDataSet.fieldByname (GetMapItem (i, d)). Asinteger: = StrtoinTdef (Trim (Trim (GetcSvrecordItem (I, Recordstring)), FDEFAULTINT);
ftfloat:
Begin
Try
F: = STRTOFLOAT (TRIM (Trim (GetcSvrecordItem (I, RecordString)))
Except
F: = fdefaultint;
END;
FDataSet.fieldbyName (GetMapItem (i, d)). Asfloat: = f;
END;
Else
IF ftrimdata then
FDataSet.fieldbyName (GetMapItem (i, d)). Asstring: = Trim (GetcsvrecordItem (i, recordstring))
Else
FDataSet.fieldByname (GetMapItem (i, d)). Asstring: = getCsvrecordItem (i, recordstring);
END;
// Post Record
FDataSet.post;
Except
ON E: Exception DO
IF not fsilentexport the
Raise
Else
IF assigned (fEXPORTERROR) THEN
Begin
FEXPORTERROR (Self, E.MESSAGE, C, ErrorResponse);
IF errorResponse = pgcsvabort then
Break;
END;
END;
IF assigned (fonaddrecord) THEN
FonaddRecord (Self);
IF assigned (fEXPORTPROGRESS) THEN
FEXPORTPROGRESS (Self, C, FSTOP);
INC (C);
END;
FDataSet.enableControls;
{********************************************************************************************** ***********}
IF assigned (fafterexport) THEN
Fafterexport (Self);
// Close Table if Nessecary
IF Fautoopen Then
Begin
IF assigned (fbeforeclosetable) THEN
Fbeforeclosetable (Self);
FDataSet.Close;
IF assigned (faftercloSetable) THEN
FafterCloseTable (Self);
END;
// Close CSV File
Closefile (ffile);
// disallocate buffer
FreeMem (buffer);
ShortdateFormat: = TEMP;
// free cache
For i: = ffieldcache.count - 1 Downto 0 DO
Dispose (Ffieldcache.Items [i]);
Ffieldcache.free;
END;
(So long! I have spent my eyes. I found the core code I care about. Don't worry, I am a lazy person.) What is the difference? It is obvious, we hope to put this The time of RecordString is open. After processing, it will return to the imported operation. So, this is just an event processing process. In this process, we need to pass the value of RecordString to let the user through Delphi.
Since I don't provide this interface, I added it myself. This event cannot be defined with a standard TNOTIFYEVENT, but requires a re-declaration. The new event declaration and event properties are as follows:
Type
...
TPGCSVREGULATESTREVENT = Procedure (Sender: Tobject; var defordstring: string) OF Object;
...
TPGCSV = Class (Tcomponent)
Published
Property Regulate: TPGCSVREGULATESTREVENT READ FREGULATESTRING WRITE FREGULATESTRING
// Don't forget to press CTRL SHIFT C after writing
...
END;
Ok, now you can write an event calling method in the local write event call.
...
While (Not Eof (FSTOP) DO
Begin
// read from CSV
Readln (FFile, Recordstring);
// xm4014's mode
IF assigned (fregulateString) THEN
Fregulatestring (Self, Recordstring);
// Add New Record
Try
FDataSet.Append;
...
After re-compiling the package file, you will find the regulatestring event in the event page of the TPGCSV control, double-click it to add your processing code. In this way, regardless of the weird characters or formats in the text data, we all filtered the first filtering of this event, let the control of the control of the control. Simple (too simple, I still have written so long! Khan)
But is this?