Как экспортировать текстовый файл для каждого цикла? - PullRequest
1 голос
/ 05 июня 2019

Я написал программу для экспорта файла в определенный каталог, и я чувствую, что написал какую-то нежелательную логику. поэтому я хотел бы знать короткий и лучший способ сделать экспорт файлов. Позвольте мне поделиться тем, что я пытался

DEFINE VARIABLE cData AS CHARACTER NO-UNDO.
DEFINE VARIABLE i     AS INTEGER NO-UNDO.
DEFINE VARIABLE icount AS INTEGER NO-UNDO.
DEFINE VARIABLE cName AS CHARACTER NO-UNDO.
DEFINE VARIABLE cPath AS CHARACTER NO-UNDO.

DEFINE TEMP-TABLE ttdata
    FIELD GetName  AS CHARACTER 
    FIELD iValue   AS INTEGER.

ASSIGN
    icount = 2
    cPath  = "*******".

DO I = 1 TO icount:
    IF I = 1  THEN cName = "David".
    IF I = 2  THEN cName = "Macavo".


   CREATE ttdata.
   ASSIGN
        ttdata.GetName = cName
        ttdata.iValue  =  100.
END.

/** ttdata has two records now*/
FOR EACH ttdata.
    RUN CallProc.p (INPUT ttdata.GetName,
                    INPUT ttdata.iValue).
END.

PROCEDURE CallProc:

    DEFINE INPUT PARAMETER getName AS CHARACTER NO-UNDO.
    DEFINE INPUT PARAMETER iValue  AS INTEGER   NO-UNDO.

    OUTPUT TO cPath.
    PUT UNFORMATTED ttdata.GetName ttdata.GetName.
    OUTPUT CLOSE.
END PROCEDURE.

Судя по моей логике, он работает хорошо и экспортирует 2 файла, как я и ожидал, но его плохая идея вызвать другую процедуру. Пожалуйста, помогите в этом случае.

Ответы [ 3 ]

2 голосов
/ 05 июня 2019

Если вы хотите два (или более) отдельных файла экспорта, вам нужно дать им уникальные имена. Я сделал это здесь, повторно используя вашу переменную 'I' и каждый раз переназначая cPath. И хотя я не согласен с тем, что вызов отдельной процедуры для записи файла - плохая идея, я включил ее в один цикл FOR-EACH. Я также исправил некоторые замечания, сделанные idspispopd.

DEFINE VARIABLE i     AS INTEGER NO-UNDO.
DEFINE VARIABLE icount AS INTEGER NO-UNDO.
DEFINE VARIABLE cName AS CHARACTER NO-UNDO.
DEFINE VARIABLE cPath AS CHARACTER NO-UNDO.

DEFINE TEMP-TABLE ttdata NO-UNDO
    FIELD GetName  AS CHARACTER 
    FIELD iValue   AS INTEGER.

ASSIGN
    icount = 2.

DO I = 1 TO icount:
    /* Using a CASE statement makes it easier to add in other values in the future */
    CASE I:
        WHEN 1 THEN cName = "David".
        WHEN 2 THEN cName = "Macavo".
    END CASE.

    CREATE ttdata.
    ASSIGN
        ttdata.GetName = cName
        ttdata.iValue  =  100.
END.

/** ttdata has two records now*/
I = 1.
FOR EACH ttdata NO-LOCK:

    cPath = ".\" + STRING(I) + ".txt".

    OUTPUT TO VALUE(cPath).
    PUT UNFORMATTED ttdata.GetName ttdata.iValue SKIP.
    OUTPUT CLOSE.

    I = I + 1.
END.
2 голосов
/ 05 июня 2019

Я собираюсь использовать sports2000 db в моем примере.У каждого есть копия, поэтому образец легко запустить.

define stream outFile.  /* using a named stream rather than the default, unnamed, stream avoids unintended conflicts if someone else's code is lazily using the unnamed stream */

function mkTemp returns character ( input tmpid as character, input extension as character ):

  define variable fname as character no-undo.
  run adecomm/_tmpfile.p ( tmpid, extension, output fname ).

  /* create the temp file with no content
   */

  output stream outFile to value( fname ).
  output stream outFile close.

  return fname.

end.


procedure doStuff:

  define input parameter tmpfile as character no-undo.
  define input parameter custid  as integer   no-undo.

  output stream outFile to value( tmpFile ) append.  /* open the existing file in append mode */

  put stream outFile "customer:" custId skip.
  for each order no-lock where order.custNum = custId and orderStatus <> "shipped" and salesRep = "bbb":
    put stream outFile orderNum " " promised skip.
  end.

  output stream outFile close.

  return.

end.

define variable i       as integer no-undo.
define variable tmpName as character no-undo.

/* tmpName = mkTemp( "xyzzy", ".tmp" ). */  /* if you only need one temp file get the name here and comment it out below */

for each customer no-lock:

  tmpName = mkTemp( "xyzzy", ".tmp" ).  /* use this if every customer should get a distinct temp file */

  run doStuff ( tmpName, custNum ).

  /* if there is no good reason to be calling the doStuff() procedure then just remove it and do it inline like this: */

  /*
   *
  output stream outFile to value( tmpFile ) append.  /* open the existing file in append mode */

  put stream outFile "customer:" customer.custNum skip.
  for each order no-lock where order.custNum = customer.CustNum and orderStatus <> "shipped" and salesRep = "bbb":
    put stream outFile orderNum " " promised skip.
  end.

  output stream outFile close.

   */

  i = i + 1.
  if i >= 3 then leave.  /* just do 3 customers for the sample run... */

end.
2 голосов
/ 05 июня 2019

На первый взгляд программа выглядит не так уж плохо, но есть несколько проблем.

TEFP-TEFLE DEFINE может использовать NO-UNDO.

Вам, вероятно, следует использовать «FOR EACH ttdata:» вместо «FOR EACH ttdata». который в старом стиле.

Вы используете CallProc.p, который является внешней программой, а не внутренней процедурой, включенной в ваш пример. Если ваш код действительно работает, вам нужно будет показать нам код в CallProc.p.

Исходя из кода CallProc, открываемый файл называется cPath. (Я не понимаю, почему говорят, что два файла записаны.) Если вы хотите, чтобы файл назывался "*******", вы должны написать значение (cPath) вместо cPath, но "**** *** "в любом случае это недопустимое имя в Windows.

Не слишком больно запускать процедуру для каждой строки. Большая проблема в том, что вы открываете и закрываете файл каждый раз. Откройте файл перед каждым и закройте его потом. Если вы используете текущую версию OpenEdge, вы должны закрыть ее внутри блока finally.

Также вы открываете файл без APPEND, что означает, что вы перезаписываете его каждый раз, поэтому записывается только последняя запись.

Что касается неиспользования процедуры, то это должно быть довольно тривиально, тем более что вы не используете параметры, передаваемые процедуре. В настоящее время вы выводите ttdata.GetName дважды, хотя это, вероятно, ошибка. Также вы пропускаете SKIP в конце оператора put и пробел между ними, так как UNFORMATTED не добавляет пробелы. Я полагаю, вы должны были написать PUT UNMORMATTED getName "" iValue skip.

Полагаю, это какая-то домашняя работа?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...