Re: CSV ファイルのデータを直接 tabular/supertabular に?

名前: トノ
日時: 2001-11-30 18:56:40
IPアドレス: 150.35.254.*

>>4105 近藤さんは、すでに perl を利用する方向に向かっておられるようですが、 TeX から CSV ファイルを読込んで処理するというのもおもしろそうに 思えてきたんで、遊びのつもりで行き当たりばったり作ってみました。 (トニイさんの発言からすると、@nifty で過去ログをみればそれで すんだのかも・・・・) 読込む CSV ファイルは、単純に数値がカンマで区切られて並んでいるものと 仮定しています。引用符で囲まれた文字列型のデータとか、文字列型のデータの 中の特殊文字とかの対処はそう難しくないと思いますが、引用符で囲まれた 文字列の中にコンマが出現するケースに対応するのはやっかいなように 思います。 CSV ファイルからの読み込みは1行ずつ処理していますが、それをトークン リスト・レジスターにため込んだうえで、マクロの最後の方で一気に はき出しています(CSV ファイルのサイズによっては、メモリー不足などが おこるかも)。tabular 環境の中では、そうしないとループがうまく回って くれません(CSV ファイルの1行目だけが出力される)。tabular 環境中での \\ コマンドが、相当凝った処理をしているので、\loop〜\repeat の対応が うまくとれなくなっているのではないかと思いますが、正確なところは わからず、対応策も思い浮かびません。どなたかご教示いただけると 嬉しいです。 #4099 では、小数点での位置あわせを希望しておられるようですが、 この点も未対応です。tools バンドルの dcolumn パッケージあたりを使えば 可能なのでしょうか。ただし、小数点がマクロの引数に埋め込まれて しまううえ、トークンリスト・レジスターに一旦格納したうえで 処理されるので、dcolumn の仕掛けが小数点をちゃんと識別してくれるか あやしいところです。 ======== TeX ソース ================================================== \documentclass{article} \makeatletter \newread\Csv@File \newtoks\Csv@Body \chardef\Csv@Max=10 % カラム数 \def\InputCsv{% \openin\Csv@File foo.csv % CSV ファイル名 \ifeof \Csv@File %====== CSV ファイルが見つからない場合は、\closein するだけに % したいところだが、それだと表の最後の \hline などで % エラーになるので、\\ を付加して空白の行を % 作ってしまう。 \closein\Csv@File\\% \else \InputCsv@ \fi } \def\InputCsv@{% \loop %====== \endlinechar を変えておかないと、 % 最終カラムの後ろに空白が入ってしまう。 % CSV ファイル中の特殊文字の対処も、 % やるとすればここでカテゴリー・コードを % 変更して・・・ということだろうが、 % カテゴリー・コードの変更をグループに % 閉じこめたうえで \Csv@Line の定義は % そのグループの外でも使えるようにしなければ % ならない。面倒くさいのでとりあえずパス。 \advance\endlinechar by\@M \read\Csv@File to\Csv@Line \advance\endlinechar by-\@M \ifeof \Csv@File \else \@tempcnta=\@ne \@for\reserved@a:=\Csv@Line\do{% \expandafter\edef\csname Csv@Column\number\@tempcnta \endcsname{\reserved@a}% \advance\@tempcnta by\@ne }% \@tempcnta=\@ne \@temptokena={}% \@whilenum\@tempcnta<\Csv@Max\do{% \edef\reserved@a{% \the\@temptokena \expandafter\noexpand\csname CsvFmt\number\@tempcnta \endcsname{% \csname Csv@Column\number\@tempcnta\endcsname }% }% \@temptokena=\expandafter{\reserved@a &}% \advance\@tempcnta by\@ne }% \edef\reserved@a{% \the\@temptokena \expandafter\noexpand\csname CsvFmt\number\Csv@Max \endcsname{\@nameuse{% Csv@Column\number\Csv@Max }}% \noexpand\\% }% \@temptokena=\expandafter{\reserved@a}% \edef\reserved@a{\the\Csv@Body\the\@temptokena}% %====== ここですんなり \reserved@a としたいのだが % それではループがうまく回ってくれない。 % 仕方がないのでトークンリスト・レジスターに % ため込んでお茶を濁す。 \Csv@Body=\expandafter{\reserved@a}% \repeat %====== \Csv@Body を出力する前にクローズしておかないと、 % 最後に \hline など、\noalign を利用するコマンドが % 使えなくなってしまう。 \closein\Csv@File \the\Csv@Body }% end of \def\InputCsv@ %====== もう少し気の利いた出力例を考えつかないものか \@namedef{CsvFmt1}#1{(#1)} \@namedef{CsvFmt2}#1{\romannumeral#1\relax} \@namedef{CsvFmt3}#1{\textbf{#1}} \@namedef{CsvFmt4}#1{$\lim_{x\to#1}f(x)$} \@namedef{CsvFmt5}#1{\itshape#1} \@namedef{CsvFmt6}#1{\fbox{\tiny#1}} \@namedef{CsvFmt7}#1{\raisebox{-\normalbaselineskip}[\z@][\z@]{#1}} \@namedef{CsvFmt8}#1{#1} \@namedef{CsvFmt9}#1{[#1]} \@namedef{CsvFmt10}#1{$\pm#1\%$} \makeatother \begin{document} \noindent\begin{tabular}{*{10}c} \hline 1st&2nd&3rd&4th&5th&6th&7th&8th&9th&10th\\ \hline \InputCsv \hline \end{tabular} \end{document} ======================================================================== ======== foo.csv ===================================================== 11,12,13,14,15,16,17,18,19,10 21,22,23,24,25,26,27,28,29,20 31,32,33,34,35,36,37,38,39,30 41,42,43,44,45,46,47,48,49,40 51,52,53,54,55,56,57,58,59,50 ========================================================================

この書き込みへの返事:

お名前
題名 
メッセージ(タグは <a href="...">...</a> だけ使えます)