home *** CD-ROM | disk | FTP | other *** search
/ Inside Multimedia 1995 October / IMM1095.ISO / share / dfue / showcim / paradox.tx_ / paradox.tx
Text File  |  1995-05-24  |  16KB  |  439 lines

  1. ; ----------------------------------------------------------------------------------------------------
  2. ;
  3. ; Install:
  4. ;    - Run PARADOX 5.0
  5. ;    - Create a new Script file and REMOVE all its default contents
  6. ;    - Copy the contents of this file into the new opened script
  7. ;    - Run it
  8. ;
  9. ; This script is delivered as a text file, so anyone who don't have Paradox 5.0 can read it anyway
  10. ; and can modify it, if it doesn't work with an older release of Paradox.
  11. ;
  12. ; ----------------------------------------------------------------------------------------------------
  13. ;
  14. ; Import ShowCIM and ShowCIM for Windows. Version 1.0
  15. ;
  16. ; This Paradox 5.0 script can be used to import files created with ShowCIM V1.5 or later using the
  17. ; /DB switch or with ShowCIM for Windows with the 'Database export' option checked.
  18. ; The import command of Paradox uses the carriage return as an end of record (in a text file), and
  19. ; message bodies are full of CR, so I've written the script to get round this problem (Eh Mr Borland,
  20. ; why didn't you think of it?).
  21. ;
  22. ;
  23. ; Use: Simply run the script. You will be asked for some files/table locations...
  24. ;      When running, press CTRL BREAK to stop the script...
  25. ;
  26. ;
  27. ; It's freeware and you can give it to anybody. Just let me know if you add some features (if you want
  28. ; to share it with other users). Thanks for any comment, suggestion...
  29. ;
  30. ; Here is the structure of the table auto-created for import (all fields are Text-type)
  31. ;
  32. ;    Field         | Length used | Length suggested (tested over 2500 CompuServe thread files)
  33. ;    --------------+-------------+------------------------------------------------------------
  34. ;    File          | 130         | *  12 (If only the file name is given, no path with it)
  35. ;    Type          | 50          | *  40
  36. ;    Forum         | 50          |    50
  37. ;    Section       | 50          |    50
  38. ;    Message_ID    | 6           |    6
  39. ;    Parent_ID     | 6           |    6
  40. ;    Subject       | 255         | *  80
  41. ;    To            | 50          |    50
  42. ;    To_ID         | 50          | *  11 (Be careful, CompuServe addresses are 11 char. long but
  43. ;                  |             |        some other adresses can be longer like Internet addresses)
  44. ;    From          | 50          |    50 (See above for extra comment)
  45. ;    From_ID       | 50          | *  11
  46. ;    Creation_Date | 8           |    8
  47. ;    Creation_Time | 8           |    8
  48. ;    Message_Body  | 25          | *  100 (This field is a Memo field)
  49. ;    --------------+-------------+------------------------------------------------------------
  50. ;    In database   | 1024 bytes  | 512 bytes
  51. ;    --------------+-------------+------------------------------------------------------------
  52. ;
  53. ; The script does NOT test all possible errors, but tests inserting fields in the table and generates
  54. ; an error table containing the file name and the error message. When an error occurs, the process is
  55. ; stopped for the current record and goes to the next. Analyzing the last field inserted in the table
  56. ; for this file will show you where the error is located.
  57. ;
  58. ; I'm thinking about building a complete Paradox application... in the future
  59. ;
  60. ; Gildas Quiniou, Paris/France    CIS-ID:100432,500    December 29, 1994
  61. ;
  62. ; ----------------------------------------------------------------------------------------------------
  63.  
  64. Var
  65.    File        TextStream                             ; Text file descriptor
  66.    Files,
  67.    Fields      Array[] String                         ; The fields for each message
  68.    FilesLoopVar,
  69.    NFiles      SmallInt
  70.    Line,                                              ; A line read in the text file
  71.    FileName,                                          ; Text file name
  72.    ErrorTable  String                                 ; Error file name
  73.    PosInLine   Number                                 ; Index in the line read
  74.    NLines      LongInt
  75.    Threads     TCursor                                ; TCursor opened on the table
  76.    NErrors     SmallInt                               ; Number of errors encountered
  77. EndVar
  78.  
  79. Const
  80.    QUOTE="\""                                         ; Field separator
  81.    N_FIELDS=14                                        ; Number of fields per record
  82.    MAX_READLINE=1023                                  ; Max size for a string
  83. EndConst
  84.  
  85. ;
  86. ; Read a line in the text file.
  87. ;
  88. ; Paradox limits the size of a string read with ReadLine() to 1023 caracters.
  89. ; This procedure can read strings up to the 32000 caracters limit of string variables.
  90. ; This is enough for most messages...
  91. ;
  92.  
  93. Proc MyReadLine(Var Buffer String) Logical
  94.    Var
  95.       TmpBuf   String                                 ; Temporary string
  96.       TmpFile  TextStream                             ; File descriptor to open temporarily the file twice
  97.       Position LongInt                                ; The offset in the text file
  98.    EndVar
  99.  
  100.    Buffer=""                                          ; Nothing has been read
  101.    While TRUE                                          ; I use QuitLoop to break the process
  102.       Position=File.Position()
  103.       If Not File.ReadLine(TmpBuf) Then               ; Try to read a line
  104.          Return FALSE                               ; Nothing else to read
  105.       EndIf
  106.  
  107.       Message("File: "+Files[FilesLoopVar]+"   |   "+String(FilesLoopVar)+" / "+String(NFiles)+"   |   Errors: "+String(NErrors)+"   |   Lines: "+String(NLines))
  108.  
  109.       Buffer=Buffer+TmpBuf                            ; Merge the string read with the previous part read
  110.       If TmpBuf.Size()=MAX_READLINE Then             ; If the string read has a size of 1023 :
  111.                                                       ;   - Either the string is really 1023 char. long (it's very rare)
  112.                                                       ;   - Or the string is longer but Paradox hasn't read more, and
  113.                                                       ;     we need to do the job for it...
  114.          If Not TmpFile.Open(FileName,"r") Then       ; So, open the text file temporarily
  115.             ErrorShow()
  116.             Return FALSE
  117.          EndIf
  118.          TmpFile.SetPosition(Position+MAX_READLINE)   ; Seek for the next character to be read
  119.          If TmpFile.Eof() Then
  120.             TmpFile.Close()
  121.             Return TRUE
  122.          EndIf
  123.          TmpFile.ReadChars(TmpBuf,1)                  ; Read this character
  124.          If TmpBuf="\r" Or TmpBuf="\n" Then            ; If it's an carriage return, this means the whole line has been read
  125.             TmpFile.Close()
  126.             Return TRUE                                ; MyReadLine() is OK
  127.          EndIf
  128.          TmpFile.Close()
  129.          File.SetPosition(Position+MAX_READLINE)      ; To be sure, Paradox is going to read the good things
  130.       Else
  131.          NLines=NLines+1
  132.          Return TRUE                                   ; The length of the line read is less than 1023, it's OK
  133.       EndIf
  134.    EndWhile                                           ; Another turn...
  135. EndProc
  136.  
  137. ;
  138. ; Because quotes are doubled in fields, we need to convert double quotes into single ones
  139. ;
  140.  
  141. Proc StripDoubleQuotes(Var Field String)
  142.    Var
  143.       MyString String
  144.       LoopVar,
  145.       Len      Number
  146.    EndVar
  147.  
  148.    MyString=""
  149.    LoopVar=2
  150.    Len=Field.Size()
  151.    While LoopVar<Len
  152.       MyString=MyString+Field.Substr(LoopVar)
  153.       If Field.Substr(LoopVar)=QUOTE Then
  154.          LoopVar=LoopVar+1
  155.       EndIf
  156.       LoopVar=LoopVar+1
  157.    EndWhile
  158.    Field=MyString.ToANSI()
  159. EndProc
  160.  
  161. ;
  162. ; Look for the end of field begining at the 'Begin' position.
  163. ; The end of field is reached when a single quote is found.
  164. ; Returns the end position if found ou -1 if not (field continues on the next line)
  165. ;
  166.  
  167. Proc SearchEndOfField(Begin Number) Number
  168.    Var
  169.       LoopVar,
  170.       Len      Number
  171.    EndVar
  172.  
  173.    Len=Line.Size()
  174.    If Len=0 Then
  175.       Return 0
  176.    EndIf
  177.    If Len=1 Then
  178.       If Line.Substr(1)=QUOTE Then
  179.          Return 1
  180.       Else
  181.          Return 0
  182.       EndIf
  183.    EndIf
  184.    If Line.Substr(1)=QUOTE Then
  185.       If Line.Substr(2)=QUOTE Then
  186.          LoopVar=Begin+2
  187.       Else
  188.          LoopVar=Begin+1
  189.       EndIf
  190.    Else
  191.       LoopVar=Begin+1
  192.    EndIf
  193.    While LoopVar<=Len
  194.       If Line.Substr(LoopVar)=QUOTE Then
  195.          If (LoopVar=Len) Then
  196.             Return Len
  197.          EndIf
  198.          If Line.Substr(LoopVar+1)=QUOTE Then
  199.             LoopVar=LoopVar+2
  200.             Loop
  201.          EndIf
  202.          Return LoopVar
  203.       EndIf
  204.       LoopVar=LoopVar+1
  205.    EndWhile
  206.    Return 0
  207. EndProc
  208.  
  209. ;
  210. ; Retrieve the next field.
  211. ;
  212.  
  213. Proc ReadField(Var FieldRead String) Logical
  214.    Var
  215.       Len   Number
  216.    EndVar
  217.  
  218.    FieldRead=""
  219.    If PosInLine=0 Then
  220.       If Not MyReadLine(Line) Then
  221.          Return FALSE
  222.       EndIf
  223.       Len=Line.Size()
  224.       PosInLine=1
  225.    Else
  226.       Len=Line.Size()
  227.    EndIf
  228.    While TRUE
  229.       PosFin=SearchEndOfField(PosInLine)
  230.       If PosFin=0 Then
  231.          If (Len-PosInLine+1)>0 Then
  232.             FieldRead=FieldRead+Line.Substr(PosInLine,Len-PosInLine+1)+"\n"
  233.          EndIf
  234.          If Not MyReadLine(Line) Then
  235.             Return FALSE
  236.          EndIf
  237.          Len=Line.Size()
  238.          PosInLine=1
  239.          Loop
  240.       Else
  241.          FieldRead=FieldRead+Line.Substr(PosInLine,PosFin-PosInLine+1)
  242.          If (PosFin=Len) Or (PosFin=Len+1) Then
  243.             PosInLine=0
  244.          Else
  245.             PosInLine=PosFin+2
  246.          EndIf
  247.          Return TRUE
  248.       EndIf
  249.    EndWhile
  250. EndProc
  251.  
  252. ;
  253. ; Write a record in the table field by field. If an error occurs, the error message is
  254. ; written in an error table and it beeps. The process aborts for this record and continues
  255. ; with the next one
  256. ;
  257.  
  258. Proc WriteFields() Logical
  259.    Var
  260.       LoopVar  SmallInt
  261.       Errors   TCursor
  262.       TheError String
  263.    EndVar
  264.  
  265.    Try
  266.       Threads.InsertRecord()
  267.       For LoopVar From 1 To N_FIELDS
  268.          StripDoubleQuotes(Fields[LoopVar])
  269.          If Not Threads.SetFieldValue(LoopVar,Fields[LoopVar]) Then
  270.             TheError=ErrorMessage()
  271. ;           ErrorShow()
  272.             Errors.Open(ErrorTable)
  273.             Errors.Edit()
  274.             Errors.InsertRecord()
  275.             Errors.SetFieldValue(1,FileName)
  276.             Errors.SetFieldValue(2,NLines)
  277.             Errors.SetFieldValue(3,TheError)
  278.             Errors.Close()
  279.             Beep()
  280.             NErrors=NErrors+1
  281.             QuitLoop
  282.          EndIf
  283.       EndFor
  284.       Fields.Empty()
  285.       Return TRUE
  286.    OnFail
  287.       ErrorShow()
  288.       Return FALSE
  289.    EndTry
  290. EndProc
  291.  
  292. ;
  293. ; Retrieve all fields in a record. Then it verifies the number of fields read.
  294. ; If it's OK it writes the record in the table, otherwise it does nothing and
  295. ; go to the next record.
  296. ;
  297. ; NB : What shall I do if the number of fields is not good ?...
  298. ;
  299.  
  300. Proc RetrieveFields(FileName String) Logical
  301.    Var
  302.       FieldRead   String
  303.    EndVar
  304.  
  305.    MyReadLine(Line)
  306.    Fields.Empty()
  307.    PosInLine=0
  308.    While TRUE
  309.       If Not ReadField(FieldRead) Then
  310.          Return TRUE
  311.       EndIf
  312.       Fields.AddLast(FieldRead)
  313.       If Fields.Size()=N_FIELDS Then
  314.          If Not WriteFields() Then
  315.             Return FALSE
  316.          EndIf
  317.       EndIf
  318.    EndWhile
  319. EndProc
  320.  
  321. ;
  322. ; Opens a thread on the table and compute each file found in the 'SourcePath' path.
  323. ; An info message is printed at the bottom of the window:
  324. ;    Name of file / File number / Number of files / Number of errors
  325. ;
  326.  
  327. method run(var eventInfo Event)
  328.    Var
  329.       List        FileSystem
  330.       BeginTime   LongInt
  331.       TableName,
  332.       SourcePath  String
  333.       FBI         FileBrowserInfo
  334.       NewTable    Table
  335.    EndVar
  336.  
  337.    If MsgQuestion("Create Table","You will choose the path where files to import are located (wildcard '*.*' will be used)\n\nOK to proceed?")="No" Then
  338.       Return
  339.    EndIf
  340.    FBI.AllowableTypes=fbFiles
  341.    FBI.PathOnly=TRUE
  342.    If Not FileBrowser(SourcePath,FBI) Then
  343.       Return
  344.    EndIf
  345.    If MsgQuestion("Create Table","You will be asking for the name and location of the import table.\nGive a name up to 8 characters...\n\nOK to proceed?")="No" Then
  346.       Return
  347.    EndIf
  348.    While TRUE
  349.       If Not FileBrowser(TableName) Then
  350.          Return
  351.       EndIf
  352.       If Not IsTable(TableName) Then
  353.          QuitLoop
  354.       EndIf
  355.       If MsgQuestion("","The table '"+TableName+"' exists... Do you want to append?")="Yes" Then
  356.          QuitLoop
  357.       EndIf
  358.    EndWhile
  359.    If Not IsTable(TableName) Then
  360.       NewTable=Create TableName With        ; I suggest you the values below to save more space.
  361.                                              ; Tested over 2500 CompuServe thread files with no broblem
  362.          "File"            : "A130",       ; A12 (If only the file name is given, no path with it)
  363.          "Type"            : "A50",           ; A40
  364.          "Forum"           : "A50",
  365.          "Section"         : "A50",
  366.          "Message_ID"      : "A6",
  367.          "Parent_ID"       : "A6",
  368.          "Subject"         : "A255",       ; A80
  369.          "To"              : "A50",
  370.          "To_ID"           : "A50",           ; A11 (Be careful, CompuServe addresses are 11 char. long but
  371.                                              ; some other adresses can be longer like Internet addresses)
  372.          "From"            : "A50",
  373.          "From_ID"         : "A50",           ; A11 (see above for extra comment)
  374.          "Creation_Date"   : "A8",
  375.          "Creation_Time"   : "A8",
  376.          "Message_Body"    : "M25"            ; M100 (You can make this field as short as you want because datas
  377.                                              ; are stored in a separated .MB file)
  378.  
  379.                                              ; Each record uses 1024 bytes with the initial mode
  380.                                              ;              and  512 bytes with the suggested one
  381.       EndCreate
  382.    EndIf
  383.    If MsgQuestion("Create Table","You will be asking for the name and location of the error table.\nGive a name up to 8 characters...\n\nOK to proceed?")="No" Then
  384.       Return
  385.    EndIf
  386.    While TRUE
  387.       If Not FileBrowser(ErrorTable) Then
  388.          Return
  389.       EndIf
  390.       If Not IsTable(ErrorTable) Then
  391.          QuitLoop
  392.       EndIf
  393.       If MsgQuestion("","The table '"+TableName+"' exists... Do you want to append?")="Yes" Then
  394.          QuitLoop
  395.       EndIf
  396.    EndWhile
  397.    If Not IsTable(ErrorTable) Then
  398.       NewTable=Create ErrorTable With
  399.          "File"         : "A130",
  400.          "Line"         : "I",
  401.          "Error"        : "A150"
  402.       EndCreate
  403.    EndIf
  404.    BeginTime=CpuClockTime()
  405.    Try
  406.       Threads.Open(TableName)
  407.       Threads.Edit()
  408.       If SourcePath.Substr(SourcePath.Size())<>"\\" Then
  409.          SourcePath=SourcePath+"\\"
  410.       EndIf
  411.       List.EnumFileList(SourcePath+"*.*",Files)
  412.       Files.RemoveItem(".")
  413.       Files.RemoveItem("..")
  414.       NFiles=Files.Size()
  415.       If MsgQuestion("","The directory '"+SourcePath+"' contains "+String(NFiles)+" file(s)\n\nOK to proceed?")="No" Then
  416.          Return
  417.       EndIf
  418.       PosDansFichier=0
  419.       NErrors=0
  420.       For FilesLoopVar From 1 To NFiles
  421.          FileName=SourcePath+Files[FilesLoopVar]
  422. ;         Message("File: "+Files[FilesLoopVar]+"   |   "+String(FilesLoopVar)+" / "+String(NFiles)+"   |   Errors: "+String(NErrors))
  423.          If Not File.Open(FileName,"r") Then
  424.             ErrorShow()
  425.             Return
  426.          EndIf
  427.          NLines=0
  428.          If Not RetrieveFields(FileName) Then
  429.             QuitLoop
  430.          EndIf
  431.          File.Close()
  432.       EndFor
  433.       Threads.Close()
  434.    OnFail
  435.       ErrorShow()
  436.    EndTry
  437.    MsgInfo("Process status","The process is finished.\nTime: "+String((CpuClockTime()-BeginTime)/1000)+" sec.\nErrors: "+String(NErrors))
  438. endmethod
  439.