[英]How to read an excel file contents on client side?
從 JSP 頁面,我需要瀏覽 excel 文件,在系統上選擇文件后,我需要讀取該 excel 文件內容並填寫我的表格。
目前我已經嘗試使用下面的代碼,但它只在 IE 中工作,對 ActiveXObject 的 IE 互聯網選項進行了一些更改。 它不適用於其他瀏覽器。
<script>
function mytest2() {
var Excel;
Excel = new ActiveXObject("Excel.Application");
Excel.Visible = false;
form1.my_textarea2.value = Excel.Workbooks.Open("C:/Documents and Settings/isadmin/Desktop/test.xlsx").ActiveSheet.Cells(1,1).Value;
Excel.Quit();
}
</script>
請提出一些解決方案,使其適用於所有瀏覽器。
xlsx 電子表格是一個 zip 文件,其中包含一堆 xml 文件。 使用類似zip.js的東西,您可以提取 xml 文件並在瀏覽器中解析它們。 xlsx.js 就是這樣做的。 這是我的簡單示例。 為方便起見,復制到這里:
/*
Relies on jQuery, underscore.js, Async.js (https://github.com/caolan/async), and zip.js (http://gildas-lormeau.github.com/zip.js).
Tested only in Chrome on OS X.
Call xlsxParser.parse(file) where file is an instance of File. For example (untested):
document.ondrop = function(e) {
var file = e.dataTransfer.files[0];
excelParser.parse(file).then(function(data) {
console.log(data);
}, function(err) {
console.log('error', err);
});
}
*/
xlsxParser = (function() {
function extractFiles(file) {
var deferred = $.Deferred();
zip.createReader(new zip.BlobReader(file), function(reader) {
reader.getEntries(function(entries) {
async.reduce(entries, {}, function(memo, entry, done) {
var files = ['xl/worksheets/sheet1.xml', 'xl/sharedStrings.xml'];
if (files.indexOf(entry.filename) == -1) return done(null, memo);
entry.getData(new zip.TextWriter(), function(data) {
memo[entry.filename.split('/').pop()] = data;
done(null, memo);
});
}, function(err, files) {
if (err) deferred.reject(err);
else deferred.resolve(files);
});
});
}, function(error) { deferred.reject(error); });
return deferred.promise();
}
function extractData(files) {
var sheet = $(files['sheet1.xml']),
strings = $(files['sharedStrings.xml']),
data = [];
var colToInt = function(col) {
var letters = ["", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];
var col = $.trim(col).split('');
var n = 0;
for (var i = 0; i < col.length; i++) {
n *= 26;
n += letters.indexOf(col[i]);
}
return n;
};
var Cell = function(cell) {
cell = cell.split(/([0-9]+)/);
this.row = parseInt(cell[1]);
this.column = colToInt(cell[0]);
};
var d = sheet.find('dimension').attr('ref').split(':');
d = _.map(d, function(v) { return new Cell(v); });
var cols = d[1].column - d[0].column + 1,
rows = d[1].row - d[0].row + 1;
_(rows).times(function() {
var _row = [];
_(cols).times(function() { _row.push(''); });
data.push(_row);
});
sheet.find('sheetData row c').each(function(i, c) {
var $cell = $(c),
cell = new Cell($cell.attr('r')),
type = $cell.attr('t'),
value = $cell.find('v').text();
if (type == 's') value = strings.find('si t').eq(parseInt(value)).text();
data[cell.row - d[0].row][cell.column - d[0].column] = value;
});
return data;
}
return {
parse: function(file) {
return extractFiles(file).pipe(function(files) {
return extractData(files);
});
}
}
})();
您可以使用HTML5 File API在大多數現代瀏覽器中加載和打開文件客戶端
加載文件后,您可以使用支持某些 excel 輸出格式(例如 csv / xlsx)的庫來解析內容。
這里有幾個選項...
我一直這樣做——我的原型旨在讓利益相關者修改 Excel 並讓它填充 html 原型,通常不需要服務器。
( 1 ) 這是我在我的 excel 文件中放入的一個方便的按鈕宏,允許輕松保存為 XML(並重新保存為 xls):
Sub SaveAndExportXML()
Dim fname As String
Dim fnamexml As String
fname = ThisWorkbook.FullName
fnamexml = Replace(fname, ".xls", ".xml", 1, 1, vbTextCompare)
If MsgBox("Will save the following (runtime XML and source XLS) files: " & vbNewLine & "XML: " & fnamexml & vbNewLine & "Src: " & fname & vbNewLine & vbNewLine & "Ok? If so, please click Yes here and on the next 3 prompts...", vbYesNo) = vbNo Then Exit Sub
ActiveWorkbook.SaveAs Filename:=fnamexml, FileFormat:=xlXMLSpreadsheet, ReadOnlyRecommended:=False, CreateBackup:=False
're-save as xls:
ActiveWorkbook.SaveAs Filename:=fname, FileFormat:=xlNormal, Password:="", WriteResPassword:="", ReadOnlyRecommended:=False, CreateBackup:=False
End Sub
( 2 )解析JS比較復雜,但前提很簡單。 將有 XML 對象,如 Worksheet、Table、Row、Cell 和 Data。 還有一個名為 ss:Index 的 XML 屬性有時我覺得很方便。
這適用於所有主要瀏覽器。
https://catamphetamine.github.io/read-excel-file/
<input type="file" id="input" />
import readXlsxFile from 'read-excel-file'
const input = document.getElementById('input')
input.addEventListener('change', () => {
readXlsxFile(input.files[0]).then((data) => {
// `data` is an array of rows
// each row being an array of cells.
})
})
在上面的示例中, data
是原始字符串數據。 通過傳遞schema
參數,可以將其解析為具有嚴格模式的 JSON。 有關示例,請參閱 API 文檔。
API 文檔:http: //npmjs.com/package/read-excel-file
通常不可能在瀏覽器中通過 JavaScript 讀取/寫入任何文件。 因此,如果沒有任何其他插件,您將無法從瀏覽器讀取/寫入 Excel 文件。 Excel 的 ActiveX 對象允許您這樣做,但只有 IE 支持 ActiveX 對象。
其他瀏覽器可能還有其他插件,但我不知道。
首先,你為什么要這樣做? 能給個用例嗎? 也許有比您正在嘗試的更好的選擇。
更新
您必須將 excel 文件傳遞到服務器並在服務器端讀取 excel(例如在 servlet 中)。
您必須在 JSP 中的多部分表單中使用<input type='file'>
<form name="myForm" action="myServlet" enctype="multipart/form-data" method="post">
在服務器端,您可能想要使用Apache Commons File Upload 。
一旦有了文件(或上面的流),您就可以使用Apache POI HSSF/XSSF解析文件,然后將數據更新到數據庫或將其傳遞回 JSP
使用 SheetJS 和 ECMAScript,您可以執行以下操作:
將此添加到您的文件中:
import { read, writeFileXLSX, utils } from "https://cdn.sheetjs.com/xlsx-0.18.7/package/xlsx.mjs";
// returns the content of the File passed as argument as a binary string
async function readFileAsBinaryString(file) { /* use in an async function to await on the result */
const binaryString = await new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject('error : cannot read the file');
reader.readAsBinaryString(file);
});
//console.log(binaryString);
return binaryString;
}
// returns the content of the Excel File passed as argument as a CSV formatted text
async function ExcelFileToCSV(file) {
try {
const data = await readFileAsBinaryString(file);
let workbook = read(data, {
type:'binary',
});
let sheets = workbook.Sheets; // the sheets presents in the file
let length = Object.keys(sheets).length; // number of sheets in the file
if (length == 1) { // if there's only one sheet in the file
return utils.sheet_to_csv(sheets.sheet1); // returns the sheet converted to csv !! NOT AN ARRAY !!
} else if (length > 1) { // else if there are more than one sheet in the file
let returnVal = [];
for (let key in sheets) { // loop over the sheets
returnVal.push(utils.sheet_to_csv(sheets[key])); // adds the current sheet converted to csv in the returnVal array
}
//console.log(returnVal);
return returnVal; // returns an array of csv converted sheets !! ARRAY !!
}
} catch (err) {
console.log(err);
}
}
或者,您可以將其保存在另一個文件中。
如果這樣做,您將需要導出您將使用的函數並將其導入您將要使用它的文件中。
如何使用 :
async function readFile(file) { // single file
let fileContent = await ExcelFileToCSV(file);
console.log(fileContent); // log the file content
// do stuff with fileContent here
}
如果文件中只有一張sheet
,則fileContent
將包含一個字符串,否則它將是一個字符串array
,每個string
都與用於調用的文件的一張sheet
匹配。
async function readFile(files) { // multiple files
let length = files.length;
let filesContents = [];
for (var i=0; i<length; i++) {
let fc = await ExcelFileToCSV(files[i]);
filesContents.push(fc);
}
console.log(filesContents); // log filesContents
// do stuff with filesContents here
}
這樣做的好處是您可以以“同步方式”處理異步代碼。
如果您有興趣以其他格式檢索文件內容,您可以在此處查看utils.sheet_to_XXX
信息並替換ExcelFileToCSV()
中的utils.sheet_to_csv
指令,或者更好地在相應命名的另一個函數中執行此操作。
如果你想在 html 頁面中使用函數,你需要在這些腳本標簽中進行: <script type="module" defer></script>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.