Tgif Home
----
About Tgif
Current Release & Download
FAQ
Copyright Info
A Screendump of Tgif
Release History
Tools That Tgif Uses
Tools That Work with Tgif
Author of Tgif
Miscellaneous Info
----
 
Return to Tgif's Home Page
William Chia-Wei Cheng
(bill.cheng@acm.org)
 

Tgif FAQ - Mail Merge

 
How do I do mail merge for labels?
Please visit tgif's Making Labels page (clicking on this link only works if you have tgif installed and your mime settings are correct). Make sure that you double-click on the self-referenced icon near the bottom of that page if the file name you see in tgif doesn't start with "http://".
How do I do mail merge for letters?
The best way to explain this is probably with an example. Let's say that you have the following LaTeX source ("template.tex" -- this is what you need to prepare) for a job hunting letter:
    \documentstyle[11pt]{letter}
    \pagestyle{empty}
    \signature{Job Hunter}
    %
    %%TGIF_HOOK
    %
    \begin{document}
    \begin{letter}{\tgmmAddress}
    \opening{\tgmmGreeting}
    I would like to apply for a summer position at
    \tgmmPlace.
    Could you send me a copy of your application form?
    \closing{Regards,}
    \end{letter}
    \end{document}
A few things to notice here. There are a few commands used here. All of them starts with tgmm so that it's unlikely they are part of your normal document. The tgmmAddress command will be replaced by the actual address, the tgmmGreeting command will be replaced by the a greeting, and the tgmmPlace command will be replaced by the name of the company you want to send a copy of your letter to. The use of these commands is similar to the use of <<address>>, <<greeting>>, and <<place>> in a Microsoft Word document.

These commands will be defined in a file to be specified by the

    %%TGIF_HOOK
above. This file will be a temporary file generated by tgif -- referenced as $(data_fname) below.) Here is an example of what this file may look like:
    \newcommand{\tgmmAddress}{
        Mr. Bill Gates \\
        Microsoft Corporation \\
        One Microsoft Way \\
        Redmond, WA 98052}
    \newcommand{\tgmmGreeting}{Dear Bill,}
    \newcommand{\tgmmPlace}{Microsoft Corporation}

Now let's see how you can create 6 letters using tgif and the above template.

  1. Create the template file. For now, let's assume its name is "template.tex". Decide how many fields need to be data driven. For now, let's assume that you need the tgmmAddress, tgmmGreeting, and tgmmPlace fields to be data driven.

  2. Prepare the data file to drive the mail merge. Let's name this file "data.txt" (this file must have "txt" as the file extension). Since there are 3 fields, we need at least 3 columns in the data file. One more column (File) is added to the data file to specify the name of the PostScript file to be used for a specific letter. The columns are separated by ";" in "data.txt".

    The first line of "data.txt" is special. Each column in it is the name of the column (which later corresponds to the name of an attribute in a tgif object). Each name is only one word (no space) and it cannot be quoted. For example, the first line of "data.txt" is:

        File; Place; Greeting; Address
    Please note that there are only 3 semicolons separating the 4 columns.

    Each line in the rest of "data.txt" is a data line. The data in each column must be surrounded by double-quotes (and, again, separated by semicolons).

  3. Start tgif and pick a tgif label object from the Making Labels page. For this example, we will use the 5199-S - Video Tape label from the Avery Letters Collection.

    The reason for choosing this label is that the tgmmAddress field may be quite long, so it may be better to lay out the labels vertically in a single column.

  4. Create 4 separate text objects. Each of them correspond to the name of a column with "=" appended. Place them nicely inside the label object. Create 3 text objects to be used as an temporary variable. Enter "tmp_fname=", "data_fname=", and "data=" for these 3 text objects. Create 3 more text object to be used as an attribute that holds shell scripts. Enter the following for these text objects:
        cmd0=rm -f $(tmp_fname) $(data_fname);
        cmd1=
        cd /tmp;
        xterm -geom 40x8+200+400 -e latex $(tmp_fname);
        xterm -geom 40x8+200+400 -e dvips -t letter -o $(tmp_fname).ps $(tmp_fname);
    
        cmd2=
        rm -f $(tmp_fname) $(tmp_fname).aux $(tmp_fname).dvi;
        rm -f $(tmp_fname).log $(tmp_fname).ps $(data_fname)

  5. Select SelectAll() from the Edit Menu and select AttachAttrs() from the Attribute Submenu of the Special Menu.

  6. Remove the red text that reads "5199-S Video Tape" by entering into edit text mode, click inside the red text, press the <Home> key on your keyboard and press <Shift><End> to highlight the text, and finally press the <Delete> key.

  7. Select SaveNew() from the File Menu and save it as, for example, "merge-test.obj".

  8. Now, give this object a try, just to make sure that there's no problems in "data.txt". Select SelectAll() from the Edit Menu and select MergeWithTable() from the Special Menu and select "data.txt". If you get a message complained about malformed table at certain line of the data file, please fix the data file and reopen "merge-test.obj" and repeat this step until there's no error in the data file.

  9. Now it's time to fix the scripts (internal commands) specified in the "after_merge" attribute in "merge-test.obj". Open "merge-test.obj" again. The current value of the "after_merge" attribute is:
        select_obj_by_name(THIS);
        disable_undo();
        begin_animate();
        unmake_selected_obj_iconic();
        set_selected_obj_pen(0);
        hide_attr(label_type);
        hide_attr(after_merge);
        end_animate();
        enable_undo();
        unselect_all_obj()
    We don't really need to hide the red outline of the object, so we can remove the "set_selected_obj_pen(0);" line.

  10. Now let's see what we need to add. First, we need create two temporary file. We can do this by adding (right before the remaining "hide_attr(after_merge);" line):
        mktemp("/tmp/Tgif1XXXXXX", "tmp_fname");
        mktemp("/tmp/Tgif2XXXXXX", "data_fname");

  11. We then need call the "cmd0" specified above to clean up the temporary file. We then need to copy the template file to the temporary directory. This is done by:
        launch("cmd0");
        strcpy("data", "\\input{$(data_fname)}");
        create_file_using_simple_template("template.tex",
            "$(tmp_fname)", "%%TGIF_HOOK", "data");

    The create_file_using_simple_template() command above replaces the "%%TGIF_HOOK" line in "template.tex" by the "\input{/tmp/Tgif2XXXXXX}" line.

  12. Now we need to supply the data for "/tmp/Tgif2XXXXXX.tex" file (referenced as "$(data_fname).tex"). We do this by the following code:
        strcpy("data", "\\newcommand{\\tgmmPlace}{$(Place)}");
        append_attr_into_file("data", "$(data_fname).tex");
        strcpy("data", "\\newcommand{\\tgmmGreeting}{$(Greeting)}");
        append_attr_into_file("data", "$(data_fname).tex");
        strcpy("data", "\\newcommand{\\tgmmAddress}{$(Address)}");
        append_attr_into_file("data", "$(data_fname).tex");

  13. Now we need to run LaTeX and dvips, copy the resulting PostScript file back to the working directory with the specified name, and clean up the /tmp directory. This can be done by the following code:
        launch("cmd1");
        strcpy("data", "cp $(tmp_fname).ps $(File)");
        launch("data");
        launch("cmd2");

  14. We shoud hide the "cmd0", "cmd1", "cmd2", "data", "tmp_fname, and "data_fname" attributes with the following code:
        hide_attr("cmd0");
        hide_attr("cmd1");
        hide_attr("cmd2");
        hide_attr("data");
        hide_attr("tmp_fname");
        hide_attr("data_fname");

  15. After all these code is inserted, please save the file. Here is my "merge-test.obj".

  16. Now we are ready. Reopen "merge-test.obj", select SelectAll() from the Edit Menu, and select MergeWithTable() from the Special Menu and select "data.txt". If you would like to preview the PostScript file as you are performing the merge, you can change the:
        strcpy("data", "cp $(tmp_fname).ps $(File)");
    line to:
        strcpy("data", "cp $(tmp_fname).ps $(File); ghostview $(File)");