Codeunit to import a TAB delimited file

tinnertinner Member Posts: 5
I've ran into an issue though that I'm struggling to come up with a solution for and I've looked at it so long now I think it's something simple I'm just overlooking. Hoping someone can help me resolve this.

I am attempted to write a codeunit to import a tab delimited file. Found a very useful old post that got me to here. The tab delimited file contains a few fields that I'm throwing into a header record and then a description field that range in characters from 0-2K+. With the description I'm handling by doing some BigText things, passing through Waldo NavPad and putting some clean looking records in a Line table.

All works fine to a certain point. My issue occurs when a record in the file exceeds 2000 characters.
FileContent   Binary (2000)
BytesRead    Integer
FilePos         Integer
FieldNo         Integer


FeedFile.TEXTMODE(FALSE);
FeedFile.OPEN(FileName);
FieldNo := 1;
REPEAT
  BytesRead := FeedFile.READ(FileContent);
  FilePos := 0;
  REPEAT
    FilePos += 1;
    varMsg := FORMAT(FileContent[FilePos]);
    CASE FileContent[FilePos] OF
      9  : FieldNo += 1;    //  TAB
      13 : BEGIN            //  CR
             CreateHeaderRecord;
             FieldNo := 1;
             FilePos += 1;  //  CR is two
           END;
      ELSE BEGIN
        CASE FieldNo OF
          1 : Field1  := Field1  + FORMAT(FileContent[FilePos]);
          2 : Field2  := Field2  + FORMAT(FileContent[FilePos]);
          3 : Field3  := Field3  + FORMAT(FileContent[FilePos]);
          4 : Field4  := Field4  + FORMAT(FileContent[FilePos]);
          4 : varBigText.ADDTEXT(FORMAT(FileContent[FilePos]));
        END;
      END;
    END;
  UNTIL FilePos = BytesRead;
UNTIL FeedFile.POS = FeedFile.LEN;
Since that FileContent variable is binary set to the 2000 max, once I exceed the 2000 max I get an array is outside the permitted range error. Makes senese, but I'm struggling with a different method or how to restructure this code to work. I welcome any suggestions or ideas.

Comments

  • rdebathrdebath Member Posts: 383
    Sounds like you'll have to do this character by character.
    The code below should give you some idea how to work it.
    This dataport exports or imports some columns on the item table and the item picture as a hexdump.
    OBJECT Dataport 70012 Import/Export Hex Blob
    {
      OBJECT-PROPERTIES
      {
        Date=31/10/09;
        Time=10:12:34;
        Modified=Yes;
        Version List=;
      }
      PROPERTIES
      {
        FieldStartDelimiter=<None>;
        FieldEndDelimiter=<None>;
        FieldSeparator=<TAB>;
        OnPreDataport=BEGIN
                        StartTime := CURRENTDATETIME;
                      END;
    
        OnPostDataport=BEGIN
                         MESSAGE('Runtime = %1', CURRENTDATETIME - StartTime);
                       END;
    
      }
      DATAITEMS
      {
        { PROPERTIES
          {
            DataItemTable=Table27;
            OnBeforeExportRecord=BEGIN
                                   CALCFIELDS(Picture);
                                   BlobFlag := Picture.HASVALUE;
                                 END;
    
            OnAfterExportRecord=VAR
                                  InStrm@1000000000 : InStream;
                                BEGIN
                                  IF BlobFlag THEN BEGIN
                                    Picture.CREATEINSTREAM(InStrm);
                                    SaveBLOB(InStrm);
                                  END;
                                END;
    
            OnBeforeImportRecord=BEGIN
                                   BlobFlag := FALSE;
                                   CLEAR(Item);
                                 END;
    
            OnAfterImportRecord=VAR
                                  OutStrm@1000000000 : OutStream;
                                BEGIN
                                  IF BlobFlag THEN BEGIN
                                    Picture.CREATEOUTSTREAM(OutStrm);
                                    LoadBLOB(OutStrm);
                                    MODIFY;
                                  END;
                                END;
    
          }
          FIELDS
          {
            { 1    ;20   ;"No."                }
            { 22   ;30   ;Description          }
            { 53   ;10   ;"Base Unit of Measure" }
            { 64   ;12   ;"Unit Cost"          }
            {      ;     ;BlobFlag             }
          }
           }
      }
      REQUESTFORM
      {
        PROPERTIES
        {
          Width=9020;
          Height=3410;
        }
        CONTROLS
        {
        }
      }
      CODE
      {
        VAR
          StartTime@1000000001 : DateTime;
          BlobFlag@1000000000 : Boolean;
    
        PROCEDURE SaveBLOB@1000000005(VAR InStrm@1000000001 : InStream);
        VAR
          CRLF@1000000000 : Binary[2];
          Ch@1000000004 : Char;
          I@1000000007 : Integer;
          HConst@1000000003 : TextConst 'ENG=0123456789ABCDEF';
          H@1000000005 : Text[30];
        BEGIN
          CRLF[1] := 13; CRLF[2] := 10;
          H := HConst;
    
          IF NOT InStrm.EOS THEN BEGIN
            I := 0;
            CurrFile.TEXTMODE(FALSE);
            CurrFile.WRITE(CRLF);
            WHILE NOT InStrm.EOS DO BEGIN
              InStrm.READ(Ch);
    
              CurrFile.WRITE(H[Ch DIV 16+1]);
              CurrFile.WRITE(H[Ch MOD 16+1]);
    
              I += 1;
              IF I = 32 THEN BEGIN
                CurrFile.WRITE(CRLF);
                I := 0;
              END;
            END;
            IF I <> 0 THEN
              CurrFile.WRITE(CRLF);
          END;
        END;
    
        PROCEDURE LoadBLOB@1000000002(VAR OutStrm@1000000000 : OutStream);
        VAR
          Str@1000000001 : Text[250];
          I@1000000002 : Integer;
          L@1000000003 : Integer;
          Ch@1000000004 : Char;
          FD@1000000005 : File;
          InStrm@1000000006 : InStream;
        BEGIN
          // Using a temp file improves the speed a lot, single char writes to a blob are VERY slow.
          CurrFile.TEXTMODE(TRUE);
          FD.WRITEMODE := TRUE;
          FD.TEXTMODE := FALSE;
          FD.CREATETEMPFILE;
    
          WHILE (CurrFile.READ(Str) <> 0) AND (Str <> '') DO BEGIN
            L := STRLEN(Str);
            FOR I := 1 TO L DO Str[I] := Str[I] - 7 * ROUND(Str[I]/64,1,'<');
            L := L/2-1;
            FOR I := 0 TO L DO BEGIN
              Ch := (Str[I*2+1]-48)*16+(Str[I*2+2]-48);
              FD.WRITE(Ch);
              // OutStrm.WRITE(Ch);
            END;
          END;
          CurrFile.TEXTMODE(FALSE);
    
          FD.SEEK(0);
          FD.CREATEINSTREAM(InStrm);
          COPYSTREAM(OutStrm, InStrm);
          FD.CLOSE;
        END;
    
        PROCEDURE OldLoadBLOB@1000000000(VAR OutStrm@1000000000 : OutStream);
        VAR
          Str@1000000001 : Text[250];
          I@1000000002 : Integer;
          L@1000000003 : Integer;
          Ch@1000000004 : Char;
        BEGIN
          CurrFile.TEXTMODE(TRUE);
          WHILE (CurrFile.READ(Str) <> 0) AND (Str <> '') DO BEGIN
            L := STRLEN(Str);
            FOR I := 1 TO L DO Str[I] := Str[I] - 7 * ROUND(Str[I]/64,1,'<');
            L := L/2-1;
            FOR I := 0 TO L DO BEGIN
              Ch := (Str[I*2+1]-48)*16+(Str[I*2+2]-48);
              OutStrm.WRITE(Ch);
            END;
          END;
          CurrFile.TEXTMODE(FALSE);
        END;
    
        BEGIN
        END.
      }
    }
    
Sign In or Register to comment.