as400->pdf
作者:cschen33.tw@yahoo.com.tw(舊版)
新版不用PC使用tn5250中的lp5250d,請參照:nas400_pdf.html

標題文字應如右流程:As400 (print)->Personal Communication(windows) ->smb(linux)->printer->pdf
在IBM AS400的主機執行列印結果產生一個pdf的檔案
#純文字的問題:
以前的文字檔拿到windows下有一些問題,因為windows下的字型大部份非等距,而純文字並不包含字型等格式,解決方法是使用有格式的檔案格式 doc或是rtf,ps,pdf,其中一種,但是以rtf和pdf是比較好選擇

#在一些雜誌上有介紹,在windows下列印為pdf,
其流程如右:(printer(ps)->samba->ps2pdf->pdf)
這種作法和本文的作法是不同,本文的文字是向量字,而上述是產生圖形,全頁產生一個圖形,圖型在縮放時品質會變差
若是向量字時則可以保持品質

#如果你的報表是非常簡單(不是橫式是直式,且格式是A4)我們可以簡單使 用tn5250來轉換
在linux下鍵入:
lp5250 env.DEVNAME=PDFPRT outputcommand='scs2pdf > /home/pdf/SCS$$.pdf'
此如你就有一個400的列表機PDFPRT
則以下你可以忽略,高興使用了
請參考:http://csc.ocean-pioneer.com/docum/tn5250/tn5250.html

#中文:
目前有一些軟體,a2ps(linux),htmldoc(跨平台),等可以將英文轉換的很好,但是中文怎麼辦呢?
一直苦無方法,本來想直接使用bg5ps但其不像a2ps功能強大,看了一些bg5ps(ttf2psm),bg5pdf(pdflib), CIDFONT,ttf,仍然無法了解其作法,目前仍在研究ttf2psm的作法,以其能使用在別的軟體之中如a2ps,如此可以兼有bg5ps的中文功 能及a2ps的格式功能

本文章說明如何由 400列印轉為 pdf檔的設定(如果忽略Personal Communication的設定,及除檔案中的印表控制符號的動作,就是txt->pdf)
,因此我們也可以使用來將文字檔轉為pdf檔
使用到相關軟體及設定:
Personal Communication(印表機轉向,以下簡稱PC)設定請參照csc.ocean-pioneer.com/docum/p_com/pc.html
samba(linux的網路分享)
printer(設定)
dos2unix (換行的由dos的格式轉為unix的格式)
a2ps (由文字轉為ps)
gs(ps2pdf) (再將ps轉為pdf)
pdfilter(這是我使用python所寫的印表過濾程式)
如果你有其它問題可以參考網站http://www.postscript.org的 FAQ,有許多說明雖然不是滿意

以下是我實作過程的問題及解答:
如何選擇PC所設定印表機
所謂的印表機驅動程式主要是將使用者列印的文件轉為印表 機所懂 的格式,一般常見的是postscript,pcl(HP),epson等(hp及epson又可以細分成不同的版本針對不同類型的印表機)
在400系統中的報表還是以文字為主,因此我們可以在其產生的列印檔看到一些概 觀,在轉換的過程中而我們想要得到的是沒有控制碼的純文字格式,因此我們必須選擇一種格式可以較簡單的除去列印控制碼,在這三種格式中 postscript的較為複雜,因此我們排除掉(因為在400並無此類的驅動程式,否則我們將可以大大簡化轉換的過程),只考慮hp pcl或是epson,但是hp pcl的格式控制碼在每一行的啟始,而每一行都有,而epson則是除了第一行之外,其它地方的控制碼少很多,這兩種均是以ESC(027(10進位), 1B(16進位))為控制碼,最後我選擇epson,是ESC啟始到行尾的文字都可以除去就可以得到純文字格式,那epson1070就是我的選擇
如何取得PC的原始列印檔
設定一台apple laser writer(驅動程式,其實任選一個都可以)的列表機port:使用列印到檔案,Pc再設定為印表機為這一台,而400印表機驅動則是使用 epson1070,然後在400列印,則會磞出一個視窗,然後填入路徑及檔名,這個檔案就是你要的檔案
a2ps
A2ps是本主題的核心所在,我只是應用這個程式轉成我 要的PS檔,當然我也參考過其它的軟體(txt2ps,text2ps),但是均沒有這個程式強,詳讀其手冊有助應用它的其它功能(如果你升級到 redhat8.0,可能會因為編碼big5而有問題,有兩種方法解決,變更編碼/etc/sysconfig/i18n,另一種,在 /usr/share/a2ps/encoding.map中加入big5 ascii)
不支援中文
使用a2ps並不支援中文,而有另一個程式是 bg5ps,因功能太少所以無法提供我們要的格式,可是我所使用400資料庫軟體,本來就不支援中文,等於沒事
Linux下印表機的設定
無法使用cups請用LPRng印表機管理程式
在/etc有一個檔案是設定印表機printcap手動 加入下面,或是使用設定工具如webmin來設定會簡單許多:
txt2pdf|convert text to pdf:sd=/var/spool/lpd/txt2pdf:cm=convert text to pdf:sh:lp=/dev/null:if=/home/txt2pdf/txtfilter:

參數說 明如下:
sd=spool directory
cm=註解
lp=列印設備null
if=過濾程式
如果手動還要建立/var/spool/lpd/txt2pdf目錄
linux下接收列印的檔案
在linux下將列印的資料轉到,上述的if過濾程式, 是一種類似pipe,在python是使用sys.stdin取得,並使用read()將其讀出
如何取出列控制符號
在linux下有一些程式如tr,sed,都是可以用來 取代或刪除文字,經過測試的結果其無法接受特殊ESC這個符號,因此我使用python中chr(27)及re正規表示法的模組:
得到取代的正規表示法為:'['+chr(27)+'].*'
                    修正:'['+chr(27)+'][\S]*'
目前兩個都有問題,還在思考中,第1個如果會將控制碼後面 的所有的字串都刪除,也就是如果控制碼後有資料那就有問題了,第二個,會將換行符號一併除去產第一行非常的長
控制符號
在linux下man ascii你可以查到所有ascii code (8,16,10進位)
0D (\r) 按下enter
0A (\n) 換行
0C (\f) 換頁
常識:unix換 行0A,但windows 為0D 0A ,為了不弄混,在linux下均改為0A
    :在印表機epson控符號中如果出現0D(後不接0A)代表將之後的字重新在本行列印
     01234567890  1234567890          01234567890
     abcd test  \r         1  ===>    abcd test 1
     當然前後都有字則字會重疊 
dos2unix
上述的dos及unix的轉換可以使用本程式取代
dos2unix -o 檔案
其中-o代表結果蓋寫過原來檔案
python執行外部命令
模組commands,命令 getstatusoutput('外部的命令、路徑、參數'),傳回兩個值
result1,result2=commands.getstatusoutput('命令')
1.成功失敗
2.失敗的字串
另一個選擇,直接傳回
result=commands.getoutput('命令')

python的時間模組
time,其中time()取得時間的秒數, localtime()轉為本地時間tuple,strftime()
在windows下gmtime()可以不用給,但是在linux下要給
a2ps的功能選項
在我的程式中我使用的選項如下
--no-header  :不印檔頭
--borders=0  :不印邊框,內定有框線
-M letter    :紙的格式,因A4在ps2pdf時右邊會被切掉,我只有設為letter
--columns=1  :在a2ps中內定是將所有的文字檔中所有頁數自動合併為一大頁
--rows=1     :但是我要一頁就好
-r 或-R      :橫印或是直印
-l           :每行的的字數,會讓a2ps自動調整字型的大小
-o 輸入的檔名
ghostscript的安裝
如果你要安裝最新版的ghostscript,注意在安 裝程式的路徑要更改,而字型的路徑也要加入兩行
gs的字型是裝在兩個地方

txtfilter檔案內容
(由於不含錯誤處理,
強烈建議修改程式內的
錯誤處理)
#!/usr/bin/python
import sys,tempfile,commands,re,time
from time import localtime,time,strftime
dir='/home/samba/ps2pdf/'
tempdir=dir+'temp/'
output_dir='outfile/'
tempn1=tempfile.mktemp('.tmp')
tempn2=tempfile.mktemp('.txt')
tempn3=tempfile.mktemp('.ps')
maxline=0
p_dos2unix=commands.getoutput('which dos2unix')+" -o "
p_a2ps=commands.getoutput('which a2ps')+" "
p_ps2pdf=commands.getoutput('which ps2pdf14')+" "

out_file=dir+output_dir+strftime('%m%d-%H%M%S.pdf',localtime(time()))

pipefile=sys.stdin
tempf1=open(tempn1,'w+')
tempf1.write(pipefile.read())
tempf1.close()
#將dos的換行格式轉unix
a=commands.getoutput(p_dos2unix +tempn1)
tempf1=open(tempn1,'r')
line=tempf1.readline()
tempf2=open(tempn2,'w+')
repl_pattern="["+chr(27)+"].*"
while line:
     line=re.sub(repl_pattern,'',line)
     if len(line)>maxline:
        maxline=len(line)
     tempf2.write(line)    
     line=tempf1.readline()
tempf1.close()
tempf2.close()
pipefile.close()

#page width
#if width >85 then we chang the print orientation from
if maxline>=85:
   print_dir=' -r '
else:
   print_dir=' -R '

convert_opt=' --no-header --borders=0 -M letter --columns=1 --rows=1 '+print_dir+'-l '+str(maxline)+' -o '
convert_string=p_a2ps+tempn2+convert_opt+tempn3
a=commands.getoutput(convert_string)
a=commands.getoutput('/usr/bin/ps2pdf '+tempn3+" "+out_file)
a=commands.getoutput('/bin/chmod 444 '+out_file)
設定samba分享
在 /etc/samba/smb.conf加入分享資料匣
例如:
[400pdf]
       comment=400->pdf
       path=/home/txt2pdf/output
       read only= Yes
更改網域登入檔的內容
其所在的位罝nt /winnt/system32/repl/Import/Scripts,相當於在網路芳鄰\\主機\netlogon,加入net use p:\\主機\400pdf  /yes
如此一登入則有一個網路磁碟機P:
如果是samba同理更改登入檔的內容同上
換頁控制
a2ps有一個換頁控制,如同倚天的控制換頁碼♀,只要 有這個符號就可會換頁
另一個選擇ghostscript+txt2ps
在window下有同樣有ghostscript 可供使用,而txt2ps是可以將文字檔轉為ps,然後再使用ps->pdf
轉換完畢後寄信給某人
由於上述做法,並無法確定列印使用者,因此你可以參考但 卻不是很實用,使用的軟體metasend
範例:
metasend -b -F "txt2pdf converter" -f $FILE -m application/pdf -s "txt2pdf" -S 4000000 -t $TOADDR                                                            

參數說明如下:
-b 非互動式(批次模式)
-F 送件者
-f 檔名
-m 指定MIME-type(application/pdf)
-s 標題
-S 超過大小分割郵件(不指定也可以)
-t 收件人
如何測試
執行檔(印表機過濾程式)txtfilter,印表機名 稱txt2pdf
直接執行該程式
1.txtfilter < 測試檔或 cat 測試檔 | txtfilter
執行印列命令
2.lpr -Ptxt2pdf 測試檔
如果還有問題
3.在程式碼加入一個記錄檔,我你就可以在其中找到可能的錯誤訊息