Reading from / writing to files from within TGF

Use this forum for everything concerning script usage
Post Reply
dreamweaver
Newbie
Newbie
Posts: 7
Joined: Mon May 02, 2011 6:02 am

Reading from / writing to files from within TGF

Post by dreamweaver »

It took me some time to read information from a CSV-text-file based on 'artist' and 'tilte'. Probably someone else wants to do something similar so I leave the script here.
All in all TStringList is good for that purpose, but TStringList.IndexOf has some limitations. On the other hand regular expressions aren't very handy all the time, so I build something around that.

Basically the script copies a comment string from a CSV-file named commentDB.csv (format: artist;title;path;filename;comment) to the comment-field of the GodFather-grid (View > Main > Tag). This is possibly done more than one time for a specific artist + title combination.

program copy_Comment;
var
  sTmp: string;
  found: string;

  commentDBFileLocation: string;
  scriptLogFileLocation: string;

// Data read from commentCDBFile
  artistCDB: string;
  titleCDB: string;
  pathCDB: string;
  filenameCDB: string;
  commentCDB: string;

// Data read from TGF-TGFGrid
  artistTGFGrid: string;
  titleTGFGrid: string;
  filenameAndPathTGFGrid: string;
  commentTGFGrid: string;

  commentDBDataSet: string;
  noCommentDBDataSet: string;                    // commentDBDataSetString, butcomment removed
  noCommentNoPathDBDataSet: string;              // commentDBDataSetString, butcomment and path removed
                                                             
  i: integer;
  maxDBDataSetRows: integer;                    // Limits the numer of DB-rows (lines)
  commentDB_numberOfRows: integer;              // Whow many datasets in commentDB?
  noCommentDB_numberOfRows: integer;
  noCommentNoPathDB_numberOfRows: integer;
  commentDBIndexPosition: integer;              // Where am I in the commendDBFile dataset
  noCommentDBIndexPosition: integer;
  noCommentNopathDBIndexPosition: integer;

  scriptLog: TStringList;                        // Never forget to TStringList.Create (see below) !!
  commentDB: TStringList;                        // File of comments
  noCommentDB: TStringList;                      // Auxiliary list of noCommentBDataSetString,
                                                  // makes comparing strings easier
  noCommentNopathDB: TstringList;                // Similar to noCommentDB



// Procedures and functions ==============================================================

procedure garbageCollection;
// Close open files and probably some more stuff one day
begin
    commentDB.Free;
    noCommentDB.Free;
    noCommentNopathDB.Free;

    scriptLog.Append('======= Done ======');
    scriptLog.SaveToFile(scriptLogFileLocation);  // Assuming there will never be a file handling error
    scriptLog.Free;
end;


procedure myExit(lineOfCode : Integer; errorString : String);
begin
    scriptLog.Append('Error;' + intToStr(lineOfCode) + ';' + errorString);
    sys_MessageDlg('Error: ' + errorString + ' in code line ' + intToStr(lineOfCode), 3, 0);
    garbageCollection;
    exit;
end;

procedure checkComment( commentStr : string ; sourceOfCommentStr : string ; noCommentNoPathDBIndexPosition : integer );
// Cares for a well formed comment, sourceOfCommentStr signals what kind of comment (DB oder TGF) string is about to be examined.
var
  regexFindResultString : string;
  j: integer;
begin
    regexFindResultString := '';
    j := -1;
    if ( commentStr = '' ) OR ( noCommentNoPathDBIndexPosition '') AND (noCommentNoPathDBIndexPosition >= 0 ) then
        begin

            regexFindResultString := sys_RegexFindStr( commentStr , '(^[wisplgt]\d*($|\s))' , 1 );
            if ( regexFindResultString = '') then
                begin
                myExit( 85 , 'Unknown error - commentStr [' + sourceOfCommentStr + ']: ' + commentStr + ', regexFindResultString: ' + regexFindResultString + ', noCommentNoPathDBIndexPosition: ' + intToStr( noCommentNoPathDBIndexPosition ) );
                end
            else if ( regexFindResultString '') then
                begin
                // do nothing, everything's fine (string conforms to regex rule)
                end
            else
                begin
                myExit( 93 , 'Unknown error - commentStr [' + sourceOfCommentStr + ']: ' + commentStr + ', regexFindResultString: ' + regexFindResultString + ' , noCommentNoPathDBIndexPosition: ' + intToStr( noCommentNoPathDBIndexPosition ) );
                end;
        end
    else
        begin
        myExit( 98 , 'Unknown error - commentStr [' + sourceOfCommentStr + ']: ' + commentStr + ', regexFindResultString: ' + regexFindResultString + ' , noCommentNoPathDBIndexPosition: ' + intToStr( noCommentNoPathDBIndexPosition ) );
        end;
end;



procedure logMultipleOccurances( noCommentNoPathDBIndexPosition : integer; artistTGFGrid : string; filenameAndPathTGFGrid : string) ;
// There may be more datasets for a specific artist - title combination -> log them for later analysis.
var
    j : integer;
    k : integer;

begin

    j := -1;
    k := 0;
    j := noCommentNoPathDBIndexPosition;
    k := noCommentNoPathDB.Count;

    // if DB has datasets and something has been found before and index is not on last dataset
    if ( k 0 ) AND ( j > -1 ) AND ( j -1 ) then
        begin
        if ( artistTGFGrid = sys_RegexFindStr( noCommentDB[ noCommentNoPathDBIndexPosition ],'^(.*);(.*);(.*)$' , 1 ) ) AND // 1: artist
          ( titleTGFGrid = sys_RegexFindStr( noCommentDB[ noCommentNoPathDBIndexPosition ],'^(.*);(.*);(.*)$' , 2 ) ) AND // 2: title; 3: path with filename
          ( filenameAndPathTGFGrid sys_RegexFindStr( noCommentDB[ noCommentNoPathDBIndexPosition ],'^(.*);(.*);(.*)$' , 3 ) ) then
          begin
          {============= This is what it's all about ================
          But before returning what we need a) check comment string and
          b) have a look behind commentDB[ noCommentNoPathDBIndexPosition ], if there are more of this artist + title combinations
          ===========================================================}
          sTmp := '';
          sTmp := sys_ApplyCase( sys_RegexFindStr( commentDB[ noCommentNoPathDBIndexPosition ] , '^(.*);(.*);(.*);(.*);(.*)$' , 5 ) , 2 );
          checkComment(sTmp , 'DB', noCommentNoPathDBIndexPosition );
          logMultipleOccurances( noCommentNoPathDBIndexPosition, artistTGFGrid, filenameAndPathTGFGrid );
          Result := sTmp; // Return comment from commentDB
          end
        // Some consistency checking. If artist, title and path + filename match, comment has to match, too. Otherwise there is a logical error
        else if ( artistTGFGrid = sys_RegexFindStr( noCommentDB[ noCommentNoPathDBIndexPosition ] , '^(.*);(.*);(.*)$',1)) AND // 1: artist
            ( titleTGFGrid = sys_RegexFindStr( noCommentDB[ noCommentNoPathDBIndexPosition ] , '^(.*);(.*);(.*)$',2)) AND // 2: title; 3: path with filename
            ( filenameAndPathTGFGrid = sys_RegexFindStr( noCommentDB[ noCommentNoPathDBIndexPosition ] , '^(.*);(.*);(.*)$' , 3 ) ) then
            begin
            sTmp := '';
            sTmp := sys_RegexFindStr( commentDB[ noCommentNoPathDBIndexPosition ] , '^(.*);(.*);(.*);(.*);(.*)$' ,5  );
            sTmp := sys_ApplyCase( sTmp , 2 ); // Datasets in commentDB have not been lowercased yet
            if ( sTmp = commentTGFGrid ) then
              begin
              scriptLog.Append( 'Info;' + intToStr( 186 ) + ';' + 'Found match at commentDB index position ' + intToStr( noCommentNoPathDBIndexPosition ) );
              end
            else if ( sTmp commentTGFGrid ) then
              begin
              // myExit( 112 , 'Logic error - sTmp: ' + sTmp + ', commentTGFGrid: ' + commentTGFGrid + ', index: ' + intToStr( noCommentNoPathDBIndexPosition ) );
              scriptLog.Append( 'Warning;' + intToStr( 191 ) + ';sTmp: ' + sTmp + ' and commentTGFGrid: ' + commentTGFGrid + 'do not match but should (same (!) file) at index position: ' + intToStr( noCommentNoPathDBIndexPosition )  );
              end
            else
              begin
              myExit( 195 , 'Unknown error' );
              end;
            end
        else
            begin
              scriptLog.Append( 'Info;' + intToStr( 200 ) + ';' + 'Found myself at commentDB index position ' + intToStr( noCommentNoPathDBIndexPosition ) );
              Result := ''; // Kein Kopieren, da gleicher File
            end;
        end
    else if ( noCommentNoPathDBIndexPosition = -1 ) then
        begin
        Result := ''; // This should happen most of the time
        end
    else
        begin
        myExit( 210 , 'Unknown error' );
        end;
end;



//  Initialize things ======================================================================
begin

    maxDBDataSetRows := 10000;

    i := 0;

    found := '';

    commentDB_numberOfRows := 0;
    noCommentDB_numberOfRows := 0;
    noCommentNoPathDB_numberOfRows := 0;

    commentDBIndexPosition := -1;
    noCommentDBIndexPosition := -1;
    noCommentNopathDBIndexPosition := -1;

//    scriptLogFileLocation := 'C:\Documents and Settings\to\Desktop\scriptlog.txt';
    scriptLogFileLocation := 'z:\modern\scriptlog.txt';
    commentDBFileLocation := 'z:\modern\commentDB.csv';

    commentDBDataSet := '';
    noCommentDBDataSet := '';
    noCommentNopathDBDataSet := '';

    scriptLog := TStringList.Create;
    commentDB := TStringList.Create;
    noCommentDB := TStringList.Create;
    noCommentNopathDB := TStringList.Create;

    scriptLog.Append('======= Begin ======');
    scriptLog.SaveToFile(scriptLogFileLocation); // Overwrited old log with one new line

//  Read commentDB and create noCommentDB aux list =======================================

    // Read path and filename into commentDBLocation
    // Alternatives:
        // Works without path if scritp and DB-File in same folder:
          // commentDB.LoadFromFile('commentDB.csv');
        // Or use sys_OpenFileDialog:
          //commentDBLocation := sys_OpenFileDialog('commentDB2.csv', 'C:\GodFatherScripts');
    commentDB.LoadFromFile(commentDBFileLocation); // Assuming there will never occur a file handling error

    i:= 0;
    commentDB_numberOfRows := commentDB.Count;

    if ( commentDB_numberOfRows > maxDBDataSetRows ) then
      begin
      myExit( 264 , 'Number of datasets in commentDB exceeds allowed maximum of ' + intToStr( maxDBDataSetRows ) + ' rows' );
      end;

    while i '' ) then // If something found ..
            begin
            if ( tg_GetField( 'Comment' ) = '' ) then // ... and commentTGFGrid is empty ...
                begin
                tg_SetField( 'Comment', found ) // ... then copy what you have found
                tg_SetResult( 'OK - touched' );
                tg_setSkip( false );
                scriptLog.Append( 'Info;' + intToStr( 338 ) + ';' + 'Wrote to commentTGFGrid for commentDB index position ' + intToStr( noCommentNoPathDBIndexPosition ) );
                end
            else if ( tg_GetField( 'Comment' ) '') then
                begin
                tg_SetResult( 'NOK - Comment not empty: ' +  tg_GetField( 'Comment' ) ); // This should not happen,
                                            // could mean the grid's comment field have not be cleaned up properly before running the script
                                            // If it's not empty, then it should be the same file, and this as been handled before!
                tg_setSkip( true );
                scriptLog.Append( 'Warning;' + intToStr( 346 ) + ';' + 'commentTGFGrid is not empty for commentDB index position ' + intToStr( noCommentNoPathDBIndexPosition ) );
                end
            else
                begin
                tg_SetResult( 'NOK - unknown error' );
                myExit( 351 , 'Unknown error' );
                end;
            end
          else
            begin
            tg_SetResult( 'NOK - unknown error' );
            myExit( 357 , 'Unknown error' );
            end;

    until not tg_Skip;

    garbageCollection;

end.

User avatar
jtclipper
Administrator
Administrator
Posts: 768
Joined: Tue Aug 10, 2010 12:04 pm

Re: Reading from / writing to files from within TGF

Post by jtclipper »

Nice and detailed script there, if possible you can upload a small sample of the csv file for people intrested to work on something similar.
Dimitris

Post Reply