工作上固定頻率會收到User提供的設定需求資訊,檔案大多為Excel
的格式.xlsx
或.xls
,需要擷取內容的參數資訊,轉換撰寫sql
語法寫入資料庫進行操作。
既然格式都是固定的,何不動手寫個小工具,一鍵完成轉換呢?如此一來,不管設定資料的數量多寡都能瞬間完成處理。更重要的是,萬一User臨時變更需求,只要對方重新提供新的設定檔,作業都是瞬間完成的事,而且程式化也能避免人工手動鍵入更新的錯誤,蠻值得花點時間試試。
utf-8
編碼的csv
檔案,避免中文顯示亂碼或問號出現。雖然本次主要介紹透過瀏覽器進行處理,但在之前已經先用其他語言進行過實作,下面分別探討實作方式的考量:
既然目標是對本機檔案的讀寫操作,首選一定是後端語言出發,其中最簡單的方式非Python
莫屬,只不過,如果受限於公司資訊部門防火牆政策,本機可能無法進行下載或安裝。
如果公司本身使用的語言是Java
,大多不會有問題,甚至可以打包輸出成可執行的jar
檔,提供給同事們使用。但,除非系統開發上需要,我個人並不喜歡用Java
的檔案讀寫處理簡單的小程式。FileReader、FileInputStream、BufferedInputStream
或是第三方apache
的FileUtils
、Java 8
的Files
等等,雖然提供多種方式以應對多樣的使用場景,同時也造成選擇困難。
使用Node.js
來說,呼叫同步的readFileSync
使用上跟Python
不會差太多,呼叫非同步的readFile
則需要注意實作上的差異,等待callback
完成才會讀到資料。同樣,Nodejs
也可能會因防火牆政策而不能下載或安裝。
前端網頁其實可以進行檔案上傳跟下載,是否也意味著可以上傳後讓網頁取得檔案,進行處理後,再提供下載功能呢?可行的話,寫好的程式也可以分享出去,畢竟公司內電腦總不會限制不給裝瀏覽器吧?
打開vscode
,新建一個html
檔案,鍵入!
快速建立版型。
在body
區塊內加入input
標籤,並且type="file"
。
用瀏覽器打開index.html
確認結果,點擊選擇檔案會叫出檔案總管,可以選擇要上傳的檔案。
為了方便使用,加入一個點擊按鈕及一個展示區塊,並且給定展示區塊呈現大小。
<style>
#display_area {
width: 800px;
height: 600px;
}
</style>
<body>
<input type="file" id="source">
<hr>
<button id="display_btn">顯示</button><br>
<textarea id="display_area"></textarea>
</body>
script
標籤放在head
區塊,在document
加入事件監聽器,確保DOM
載入完成後才觸發執行main
。main function
。main function
只會執行一次,不會進行複用,也可以inline
進去上方監聽的程式中,改以匿名函式
或ES6
的箭頭函式的寫法,只是我個人不喜歡很多層的巢狀。main
中,選取顯示的按鈕並加入監聽click
事件,事件觸發handleDisplay
。File api
讀取上傳檔案,並將檔案內容以文字進行讀取。<script>
document.addEventListener("DOMContentLoaded", main);
function main() {
const displayBtn = document.querySelector("#display_btn");
displayBtn.addEventListener("click", handleDisplay);
}
function handleDisplay() {
const source = document.querySelector("#source");
const displayArea = document.querySelector("#display_area");
const file = source.files[0];
const fileReader = new FileReader();
fileReader.readAsText(file);
fileReader.onload = (event) => {
const fileContent = event.target.result;
displayArea.innerHTML = fileContent;
}
}
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#display_area {
width: 800px;
height: 600px;
border: 1px solid #ccc;
padding: 10px;
overflow: auto;
white-space: pre-wrap;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", () => {
const displayBtn = document.querySelector("#display_btn");
displayBtn.addEventListener("click", handleDisplay);
});
function handleDisplay() {
const source = document.querySelector("#source");
const displayArea = document.querySelector("#display_area");
const file = source.files[0];
if (!file) {
displayArea.textContent = "No file selected.";
return;
}
if (!file.type.match('text.*')) {
displayArea.textContent = "Invalid file type. Please select a text file.";
return;
}
const fileReader = new FileReader();
fileReader.readAsText(file);
fileReader.onload = (event) => {
const fileContent = event.target.result;
displayArea.textContent = fileContent;
};
fileReader.onerror = () => {
displayArea.textContent = "Error reading file.";
};
}
</script>
</head>
<body>
<input type="file" id="source">
<hr>
<button id="display_btn">顯示</button><br>
<div id="display_area"></div>
</body>
</html>
選擇本機一個spring-boot
專案的pom.xml
為例,點擊顯示後,內容顯示在下方文字區塊內。
總結一下,上述內容做到的僅有讀取本機上的檔案,將讀到的內容顯示在網頁上,內容即為fileContent
。
至於資料可以自行使用javascript
語法對fileContent
做調整,例如處理csv
檔案,可透過split
處理\r\n
拿到每一行,再對,
分割取得每一項參數資料值,整理好資料再展示到畫面上。