Delphi control (2)

zhaozj2021-02-16  47

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?

转载请注明原文地址:https://www.9cbs.com/read-27550.html

New Post(0)