2016-08-06 97 views
1

我們似乎看到越來越多關於在Excel電子表格上執行awk的問題,所以這裏是關於如何做這件事情的Q/A。如何在cygwin中使用awk打印Excel電子表格中的字段?

我有一個Excel電子表格"$D/staff.xlsx"(其中"$D"是通向我的桌面)這樣的信息:

Name Position 
Sue Manager 
Bill Secretary 
Pat Engineer 

,我想打印位置字段爲給定的名稱,例如輸出Secretary給出了輸入Bill

我目前可以保存爲CSV從Excel獲得:

$ cat "$D/staff.csv" 
Name,Position 
Sue,Manager 
Bill,Secretary 
Pat,Engineer 

,然後運行:

$ awk -F, -v name="Bill" '$1==name{print $2}' "$D/staff.csv" 
Secretary 

但是這是一個更大的任務的只是一小部分,所以我必須要能夠自動從shell腳本執行此操作,而無需手動打開Excel以導出CSV文件。我如何從運行cygwin的Windows PC執行此操作?

+0

還有更好的工具來處理比簡單的文本解析器更強大的轉換。請參閱http://unix.stackexchange.com/questions/23726/convert-a-xlsx-ms-excel-file-to-csv-on-command-line-with-semicolon-separated以及與文件類型相關的任何其他鏈接從命令行轉換。 –

+0

另外,XLSX僅僅是一個zip文件,裏面有xml文件。請參閱http://stackoverflow.com/questions/11082278/how-to-properly-assemble-a-valid-xlsx-file-from-its-internal-sub-components –

回答

2

以下VBS和外殼腳本的組合爲每一個片材在Excel電子表格的CSV文件:

$ cat xls2csv.vbs 
csv_format = 6 

Dim strFilename 
Dim objFSO 
Set objFSO = CreateObject("scripting.filesystemobject") 
strFilename = objFSO.GetAbsolutePathName(WScript.Arguments(0)) 
If objFSO.fileexists(strFilename) Then 
    Call Writefile(strFilename) 
Else 
    wscript.echo "no such file!" 
End If 
Set objFSO = Nothing 

Sub Writefile(ByVal strFilename) 
Dim objExcel 
Dim objWB 
Dim objws 

Set objExcel = CreateObject("Excel.Application") 
Set objWB = objExcel.Workbooks.Open(strFilename) 

For Each objws In objWB.Sheets 
    objws.Copy 
    objExcel.ActiveWorkbook.SaveAs objWB.Path & "\" & objws.Name & ".csv", csv_format 
    objExcel.ActiveWorkbook.Close False 
Next 

objWB.Close False 
objExcel.Quit 
Set objExcel = Nothing 
End Sub 

$ cat xls2csv 
PATH="$HOME:$PATH" 

# the original XLS input file path components 
inXlsPath="$1" 
inXlsDir=$(dirname "$inXlsPath") 
xlsFile=$(basename "$inXlsPath") 
xlsBase="${xlsFile%.*}" 

# The tmp dir we'll copy the XLS to and run the tool on 
# to get the CSVs generated 
tmpXlsDir="/usr/tmp/${xlsBase}.$$" 
tmpXlsPath="${tmpXlsDir}/${xlsFile}" 
absXlsPath="C:/cygwin64/${tmpXlsPath}" # need an absolute path for VBS to work 

mkdir -p "$tmpXlsDir" 

trap 'rm -f "${tmpXlsDir}/${xlsFile}"; rmdir "$tmpXlsDir"; exit' 0 

cp "$inXlsPath" "$tmpXlsDir" 

cygstart "$HOME/xls2csv.vbs" "$absXlsPath" 

printf "Waiting for \"${tmpXlsDir}/~\$${xlsFile}\" to be created:\n" >&2 
while [ ! -f "${tmpXlsDir}/~\$${xlsFile}" ] 
do 
    # VBS is done when this tmp file is created and later removed 
    printf "." >&2 
    sleep 1 
done 
printf " Done.\n" >&2 

printf "Waiting for \"${tmpXlsDir}/~\$${xlsFile}\" to be removed:\n" >&2 
while [ -f "${tmpXlsDir}/~\$${xlsFile}" ] 
do 
    # VBS is done when this tmp file is removed 
    printf "." >&2 
    sleep 1 
done 
printf " Done.\n" >&2 

numFiles=0 
for file in "$tmpXlsDir"/*.csv 
do 
    numFiles=$((numFiles + 1)) 
done 

if ((numFiles >= 1)) 
then 
    outCsvDir="${inXlsDir}/${xlsBase}.csvs" 
    mkdir -p "$outCsvDir" 
    mv "$tmpXlsDir"/*.csv "$outCsvDir" 
fi 

現在我們執行shell腳本,在內部調用cygstart到Excel文件是否存在命名基於Excel文件在同一目錄下,運行在一個子目錄中的VBS腳本來生成CSV文件(每頁一個)名稱(例如Excel文件staff.xlsx產生的CSV目錄staff.csvs):

$ ./xls2csv "$D/staff.xlsx" 
Waiting for "/usr/tmp/staff.2700/~$staff.xlsx" to be created: 
.. Done. 
Waiting for "/usr/tmp/staff.2700/~$staff.xlsx" to be removed: 
. Done. 

只有一個片具有默認名稱Sheet1在目標Excel文件"$D/staff.xlsx"這樣的上述輸出是一個文件​​:

$ cat "$D/staff.csvs/Sheet1.csv" 
Name,Position 
Sue,Manager 
Bill,Secretary 
Pat,Engineer 

$ awk -F, -v name="Bill" '$1==name{print $2}' "$D/staff.csvs/Sheet1.csv" 
Secretary 
相關問題