Addresslists with L^{A}TEX

Tobias Spribille

March 5, 1996

1 User’s Guide

\ForEachAdress The package adrlist provides the macro ForEachAddress as follows:

\ForEachAdress{⟨addressfile⟩}{⟨commands⟩} The parameters are:

addressfile Name of a file containing the addresses in the following structure:

<title>  Title, degree, e.g. ”Dipl.-Inf.”
<opening>  how to address the person
<sex>  the sex, for grammatical correctness

<first name>  First name
<name>  Name
-- begin address --  delimiter

n lines of address  address with variable length
-- end address --  delimiter, to be typed exactly this way
Telephone: <telephone number>  These entries may appear
Telefax: <telefax number>  in any order. They are
EMail: <eMail address>  distinguished through the
Private number: <private number> keywords before the colon ”:”.

commands L^{A}TEX-commands to typeset the read data. You can use these commands defined by the package in order to access the address data:

\Title  Title
\Opening  Opening
\Sex  Sex
\Firstname  First name
\Name  Name

\Address  Address. The lines are separated by \\
\Telephone  Telephone number
\Telefax  Telefax number
\EMail  EMail address
\PrivateNumber Private telephone number

2 The Macros

2.1 Declarations

This file provides the macro package adrlist. For various loops and conditions we require the ifthen-package.

 1 \ProvidesPackage{adrlist}[1995/12/21]
 2 \RequirePackage{ifthen}

Declare some variables: Rest controls the outer loop, which reads several entries out of the address database. If there are lines left in the file, it is true. AddressLoop is used for reading the adresses with variable length. Communication is a counter to repeat four times the recognition of the keywords for phone number, email etc.

 3 \newboolean{AddressLoop}
 4 \newboolean{Rest}\setboolean{Rest}{true}
 5 \newcounter{Communication}

2.2 Helper macros

\ifstringcompare Compare two entire strings, given in the two parameter variables, and not only tokens, like TEX does.

 6 \newcommand{\ifstringcompare}[4]{%
 7 \begingroup
 8  \let\protect=\noexpand
 9  \edef\0{#1}\edef\1{#2}%
10 \expandafter\endgroup\ifx\0\1#3\else#4\fi}

\concat Concatenate two lines of the address, with \\ as a delimiter, as it is required by e.g. the letter style.

11 \newcommand{\concat}[2]{#1\\#2}

\keyword Extract the keyword out of a line of the form ⟨keyword⟩:⟨contents⟩, i.e. the part before the colon. The pipe symbol may be replaced by any other character that won’t appear in the address data.

12 \def\keyword#1:#2|{#1}

\contents Like \keyword. Extracts the contents of the line, e.g. the phone number.

13 \def\contents#1:#2|{#2}

2.3 The user macro

\ForEachAddress This macro is the one the user directly calls. It opens the file given in #1 and reads all the addresses in a loop. For each address the L^{A}TEX-commands in #2 are executed to typeset the address in the document. After the whole file is read, it is closed again.

14 \newcommand{\ForEachAddress}[2]

15 {

16 \newread\File \openin\File=#1
17 \whiledo{\boolean{Rest}}
18 { \ReadNextAddress{\File}
19 \ifthenelse{\boolean{Rest}}{#2}{}

20 }

21 \closein\File

22 }

2.4 Main macrocode

\ReadNextAddress Here we read the next address out of the file given as #1 and save the read data into the respective variables. For the structure of the address file and the variable names, confer to section 1.

23 \newcommand{\ReadNextAddress}[1]{
24 \ifthenelse{\boolean{Rest}}{
25 \read#1 to \Title
26 \ifeof#1\setboolean{Rest}{false}
27 \else % If last address already is read, EOF should appear here
28  \ifthenelse{\boolean{Rest}}
29  {\read#1 to \Opening
30  \ifeof#1\setboolean{Rest}{false}\fi
31  }{}
32  \ifthenelse{\boolean{Rest}}
33  {\read#1 to \Sex
34  \ifeof#1\setboolean{Rest}{false}\fi
35  }{}
36  \ifthenelse{\boolean{Rest}}
37  {\read#1 to \Firstname
38  \ifeof#1\setboolean{Rest}{false}\fi
39  }{}
40  \ifthenelse{\boolean{Rest}}
41  {\read#1 to \Name
42  \ifeof#1\setboolean{Rest}{false}\fi
43  }{}
44  \ifthenelse{\boolean{Rest}}
45  {\read#1 to \Dummy
46  \ifeof#1\setboolean{Rest}{false}\fi
47  }{}
48  \setboolean{AddressLoop}{true}
49  \def\Emptystring{} \let\Address=\Emptystring
50  \def\Delimiter{-- end address -- }

Read Address, until -- end address -- appears.

51  \whiledo{\boolean{AddressLoop}}

52 {

53  \ifRest \read#1 to \Buffer \fi

54  \ifeof#1\setboolean{Rest}{false}\fi
55  \ifstringcompare{\Buffer}{\Delimiter}
56  {\setboolean{AddressLoop}{false}}{}
57  \ifthenelse{\boolean{AddressLoop}}

58 {

59  \ifstringcompare{\Emptystring}{\Address}

60 {

61  \let\Address=\Buffer % Don't add delimiters the first time

62 } 63 {

64  \begingroup     % keep redefinition of \\ local
65  \let\protect=\noexpand
66  \def\\{\noexpand\\}% make \\ not expandable
67  \edef\x{\endgroup
68  \def\noexpand\Address{\concat\Address\Buffer}%
69  }\x

70 }

71  }{}

72 }

Four informations are left. The keyword is extracted from \Buffer and compared with the defined keywords. If the comparison succeeds, the correct variable is set.

73  \def\KeyWTelephone{Telephone}
74  \def\KeyWTelefax{Telefax}
75  \def\KeyWEMail{EMail}
76  \setcounter{Communication}{0}
77  \whiledo{\value{Communication}<4}%

78 {

79  \ifthenelse{\boolean{Rest}}{
80  \read#1 to \Buffer
81  \edef\KeyW{\expandafter\keyword\Buffer|}
82  \ifstringcompare{\KeyW}{\KeyWTelephone}

83 {

84  \edef\Telephone{\expandafter\contents\Buffer|}

85 } 86 {

87  \ifstringcompare{\KeyW}{\KeyWTelefax}

88 {

89  \edef\Telefax{\expandafter\contents\Buffer|}

90 } 91 {

92  \ifstringcompare{\KeyW}{\KeyWEMail}

93 {

94  \edef\EMail{\expandafter\contents\Buffer|}

95 } 96 {

97  \edef\PrivateNumber{\expandafter\contents\Buffer|}

98 } 99 } 100 }

101  \ifeof#1\setboolean{Rest}{false}\fi
102  }{}
103  \stepcounter{Communication}

104 } 105 \fi 106 }{} 107 }

5