Определение формата даты в ячейке xlsx для электронных таблиц Excel 2007 - PullRequest
2 голосов
/ 09 февраля 2011

Я работаю с некоторым кодом, который читает данные из файлов xlsx, анализируя xml. Это все довольно просто, за исключением ячейки даты.

Даты хранятся в виде целых чисел и имеют атрибут «s», который является индексом таблицы стилей, который можно использовать для получения строки форматирования даты. Вот несколько примеров из предыдущего вопроса stackoverflow, который связан ниже:

19 = 'ч: мм: сс AM / PM';

20 = 'ч: мм';

21 = 'ч: мм: сс';

22 = м / д / гг ч: мм ';

Это встроенные строки форматирования даты из стандарта ooxml, однако, похоже, что Excel стремится использовать настраиваемые строки вместо встроенных. Вот пример формата из электронной таблицы Excel 2007. numFmtId больше 164 - это пользовательский формат.

<numFmt formatCode="MM/DD/YY" numFmtId="165"/>

Определить, нужно ли форматировать ячейку как дату, сложно, потому что единственный индикатор, который я могу найти, это formatCode. Это, безусловно, дата, но ячейки могут быть отформатированы любым количеством способов. Моя первоначальная попытка - найти Ms, Ds и Ys в formatCode, но это кажется проблематичным.

Кому-нибудь повезло с этой проблемой? Похоже, что в настоящее время стандартным библиотекам чтения Excel не хватает поддержки xlsx. Я ознакомился со стандартами и без особой удачи перекопал много файлов xlsx.

Лучшая информация, кажется, приходит из этого вопроса stackoverflow:

что означает, что открытая xml ячейка офиса содержит значение даты и времени

Спасибо!

Ответы [ 2 ]

4 голосов
/ 10 февраля 2011

Даты хранятся в виде целых чисел

В модели данных Excel действительно нет такой вещи как целое число. Все поплавок. Даты и даты - это числа с плавающей запятой, представляющие дни и дроби с переменной эпохи. Время - это доли дня.

Вроде как стандарт Excel в xlsx отсутствуют библиотеки чтения поддержка в это время.

Google ( "xlsxrd"). Чтобы быть в курсе событий, присоединяйтесь к группе python-excel .

Редактировать Я вижу, что вы уже задали вопрос там . Если бы вы задали там конкретный вопрос или ответили на мой запрос о разъяснении, у вас была бы эта информация более двух недель назад.

Взгляните на документацию xlrd. Впереди идет обсуждение дат Excel. Все это относится к Excel 2007, а также к более ранним версиям. В частности: необходимо разобрать нестандартные форматы. Необходимо иметь таблицу «стандартных» форматов индексов, которые предназначены для форматов даты. «Стандартные» форматы, перечисленные в некоторых местах, не включают форматы, используемые в локалях CJK.

Варианты для вас:

(1) Заимствовать из исходного кода xlrd, включая функцию xldate_as_tuple.

(2) Опция (1) + Получить комплект болтового соединения xlsxrd и позаимствовать его исходный код.

(3) [Рекомендуется] Получить комплект болтов xlsxrd и использовать его ... вы получаете набор API, которые работают в версиях Excel от 2.0 до 2007 и в версиях Python от 2.1 до 2.7.

0 голосов
/ 10 февраля 2011

Недостаточно просто искать Ms, Ds и Ys в коде числового формата

[Red]#,##0 ;[Yellow](#,##0)

- это совершенно правильный числовой формат, который содержит Y и D, но неформат даты.Я специально проверяю любой из стандартных символов форматирования даты / времени ('y', 'm', 'd', 'H', 'i', 's'), которые находятся вне квадратных скобок ('[' ']«).Уже тогда я обнаружил, что проскальзывает несколько ложных срабатываний, в основном связанных с бухгалтерским и валютным форматами.Поскольку они обычно начинаются либо с подчеркивания ('_'), либо с пробела, за которым следует ноль ('0') (с которым я никогда не сталкивался в формате даты, я явно фильтрую эти значения.

Часть моего (PHP) кода для определения, является ли маска формата датой или нет:

private static  $possibleDateFormatCharacters = 'ymdHis';

//  Typically number, currency or accounting (or occasionally fraction) formats
if ((substr($pFormatCode,0,1) == '_') || (substr($pFormatCode,0,2) == '0 ')) {
    return false;
}
// Try checking for any of the date formatting characters that don't appear within square braces
if (preg_match('/(^|\])[^\[]*['.self::$possibleDateFormatCharacters.']/i',$pFormatCode)) {
    return true;
}

// No date...
return false;

Я уверен, что все еще могут быть исключения, которые я пропускаю, но (еслиитак) они, вероятно, крайние случаи

...