Главная Библиотека Шаблоны и примерыJava: внутри файла MS Excel 2007. Часть четвёртая
Николай Норкин
г. Киров
notesnet@notesnet.ru
Часть первая
Часть вторая
Часть третья
В завершение загрузки архива электронной таблицы - обработка файлов xl/workbook.xml и xl/_rels/workbook.xml.rels получение заголовков листов (и соответствия файла листа и заголовка)
protected void parseWorkbook(byte[] content) {
try {
org.w3c.dom.Document document = this.stringToDocument(content);
this.sheetNames = new java.util.HashMap ();
org.w3c.dom.NodeList nodes = document.getElementsByTagName("sheet");
for (int i = 0; i < nodes.getLength(); i++) { // обработать список
org.w3c.dom.Element sheet = (org.w3c.dom.Element) nodes.item(i); // полуить ентри списка
String value = sheet.getAttribute("name");
String id = sheet.getAttribute("r:id");
this.sheetNames.put(id, value);
}
}
catch(Exception e) {}
}
protected void parseRelations(byte[] content) {
try {
org.w3c.dom.Document document = this.stringToDocument(content);
this.relations = new java.util.HashMap ();
org.w3c.dom.NodeList nodes = document.getElementsByTagName("Relationship");
for (int i = 0; i < nodes.getLength(); i++) { //
org.w3c.dom.Element sheet = (org.w3c.dom.Element) nodes.item(i); //
String target = sheet.getAttribute("Target");
String id = sheet.getAttribute("Id");
this.relations.put(id, target);
}
}
catch (Exception e) {}
}
Загрузка и обработка листа электронной таблицы
Для загрузки файлов, содержащих данные листов электронной таблицы (xl/worksheets/sheet[xx].xml), вызывается процедура loadWorksheet(name, baos.toByteArray()) с передачей полного имени файла и байтового содержимого файла
Процедура создаёт объект класса ru.medkirov.design.excel2007.Sheet
protected void loadWorksheet(String id, byte[] content) {
try {
if (this.sheets == null) this.sheets = new java.util.HashMap ();
ru.medkirov.design.excel2007.Sheet worksheet = new ru.medkirov.design.excel2007.Sheet(this, content);
this.sheets.put(id, worksheet);
}
catch(Exception e) {}
}
Класс Sheet листа электронной таблицы
Класс ru.medkirov.design.excel2007.Sheet содержит функцию получения формата значения ячейки, заданной объектом класса org.w3c.dom.Element, и функцию получения значения ячейки. Первая из упомянутых функций по значению атрибута s ячейки получает индекс формата из раздела cellXfs описания стилей (см. разбор файла стилей во второй части статьи)
public int getFormatNumber(org.w3c.dom.Element cell) {
try {
String attr = cell.getAttribute("s");
int index = Integer.parseInt(attr);
// return index;
return Integer.parseInt((String) this.workbook.getNumberFormats().elementAt(index));
}
catch (Exception e) {}
return 49;
}
В функции getValue на основе анализа формата возвращаемого значения обрабатывается приведение содержимого ячейки в нужный вид
Ещё раз следует напомнить, что в случае размещения строкового значения ячейки в отдельном файле строк xl/sharedStrings.xml (что задаётся атрибутом t="s" xml-элемента ячейки) числовое значение ячейки содержит порядковый индекс этой строки (начиная с нуля)
Значение чисел представлены своим строковым видом, о значении даты/времени смотрите чуть ниже
public Object getValue (org.w3c.dom.Element cell) {
try {
org.w3c.dom.NodeList nodes = null;
try { nodes = cell.getElementsByTagName("v");} catch (Exception e) {}
org.w3c.dom.Element element = null;
try { element = (org.w3c.dom.Element) nodes.item(0);} catch (Exception e) {}
if (element == null) {
try { nodes = cell.getElementsByTagName("f"); element = (org.w3c.dom.Element) nodes.item(0);} catch (Exception e) {}
if (element != null) return "";
element = cell;
}
String value = element.getTextContent();
if (value.equals("")) return "";
String relation = "";
try { relation = cell.getAttribute("t"); } catch (Exception e) {}
if (relation.equals("s"))
return this.workbook.getStringContent().elementAt(Integer.parseInt(value.trim()));
int index = this.getFormatNumber(cell);
if (index > 163)
return this.workbook.formatValue(Integer.toString(index), value.trim());
switch (index) {
case 0:
case 49:
return value;
case 1:
return Long.valueOf(value.trim());
case 2:
case 3:
case 4:
case 9:
case 10:
case 11:
case 37:
case 38:
case 39:
case 40:
case 48:
return Double.valueOf(value.trim());
case 14:
case 15:
case 16:
case 17:
case 18:
// дата
if (relation.equals("str"))
return this.getDate(value.trim());
return this.getDate(Double.parseDouble(value.trim()));
case 19:
case 20:
case 21:
case 45:
case 46:
case 47:
// время
return getTime(Double.parseDouble(value.trim()));
case 22:
// дата и время
return getDate(Double.parseDouble(value.trim()));
}
}
catch (Exception e) {
e.printStackTrace();
}
return "";
}
Функция приведения xml-содержимого ячейки к формату дата/время
Значение ячейки формата дата/время хранится в виде числа, целая часть которого равна количеству дней,прошедших с 31 декабря 1899 года, дробная часть - доле времени в сутках
public static java.util.Date getDate(double value) {
try {
java.util.Calendar calendar = java.util.GregorianCalendar.getInstance();
calendar.set(1899, 11, 31, 0, 0, 0);
calendar.add(java.util.Calendar.DAY_OF_YEAR, (int)Math.round(value) - 1);
calendar.add(java.util.Calendar.SECOND, (int)Math.round((value - Math.round(value)) * 24 * 60 * 60));
java.util.Date date = calendar.getTime();
return date;
}
catch (Exception e) {}
return null;
}
И последнее, что остаётся, это определить формат значения и привести к нему значения в случае не предустановленного формата (когда индекс формата в разделе cellXfs описания стилей больще 163)
В этом случае для анализа формата, описанного в разделе numFmts файла styles.xml следует обращение к объекту класса ru.medkirov.design.excel2007.NumberFormat
if (index > 163)
return this.workbook.formatValue(Integer.toString(index), value.trim());
// Workbook
public Object formatValue(String formatId, String value) {
try {
ru.medkirov.design.excel2007.NumberFormat format =
(ru.medkirov.design.excel2007.NumberFormat)
this.numberFormatMap.get(formatId);
return format.getValue(value);
}
catch (Exception e) {}
return value;
}
// NumberFormat
public Object getValue(String value) {
try {
if (this.isDateTimeFormat())
return this.getDateValue(value);
if (this.isIntegerFormat())
return new Integer(value);
if (this.isDigitalFormat())
return new Double(value);
}
catch (Exception e) {}
return value;
}
Ссылки
Java: внутри файла MS Excel 2007. Часть первая
Java: внутри файла MS Excel 2007. Часть вторая
Java: внутри файла MS Excel 2007. Часть третья
Java в Domino. Небольшой пример обработки потока
|
Опубликовано — 02/20/2022 |
| |
|
|