Уведомления

Группа в Telegram: @pythonsu

#1 Июль 2, 2016 09:11:43

Oleg_p
Зарегистрирован: 2014-10-15
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

win32com и excel даты

Всем привет!
(Win 7x64, python 2.7)
Пытаюсь считывать данные в ячейках, но как только натыкаюсь на нулевую дату (00.01.1900) возникает ошибка,
Что то вроде ранняя дата.
Порекомендуйте пожалуйста вариант, как лучше решить сию проблему!

заранее спасибо!

Офлайн

#2 Июль 2, 2016 09:34:44

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

win32com и excel даты

Oleg_p
Порекомендуйте пожалуйста вариант, как лучше решить сию проблему!
Привести ваш код и прикрепить файл из которого вы читаете данные.

:) Еще очень помогает вообще не использовать exel. Например при помощи win32com экспортировать таблицу в csv файл и работать только с ней.



Отредактировано doza_and (Июль 2, 2016 09:37:31)

Офлайн

#3 Июль 2, 2016 10:35:29

Shaman
Зарегистрирован: 2013-03-15
Сообщения: 1369
Репутация: +  88  -
Профиль   Отправить e-mail  

win32com и excel даты

xlrd мультиплатформенней, если что, но со своими заморочками.

Офлайн

#4 Июль 23, 2016 10:07:51

Oleg_p
Зарегистрирован: 2014-10-15
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

win32com и excel даты

Спасибо большое что отозвались!
К сожалению отказаться пока не получится, т.к. в работе подавляющее большинство используют excel, далее планируется постоянные отчеты репортить (так же в эксель).

Ниже код который использую

 import win32com.client, time
class Excel_data():
    def __init__(self, sheet_name):
        self.sheet_name = sheet_name
    # вытаскиваем данные example
    def print_value(self):
        self.sheets_val = self.sheet_name
        clmn = 1
        row = 1
        while self.sheet_name.Cells(row, clmn).Value:
            print(self.sheet_name.Cells(row, clmn).Value)
            clmn += 1
    def end_range(self):
        i = 1
        while self.sheet_name.Cells(3, i).Value is not None:
            data = self.sheet_name.Cells(3, i).Value
            if type(data) is unicode:
                data_2 = 'UNICODE'
            elif type(data) is float:
                data_2 = 'FLOAT'
            # elif float(data) == 0:
            elif type(data) is type(time.time):
                data_2 = 'TIME'
            else:
                data_2 = ''
            print type(data), ' ', data_2
            i += 1
if __name__ == '__main__':
    PATH_FILE = u'H:\\class_excel\\data_list.xlsx'
    SHEET_NAME = u'Лист1'
    try:
        try:
            app = win32com.client.Dispatch('Excel.Application')
            wbooks = app.Workbooks.Open(PATH_FILE)
            wsheet = wbooks.Sheets(SHEET_NAME)
            files_d = Excel_data(wsheet)
            # files_d.print_value()
            files_d.end_range()
        except Exception, e:
            print
            print('Ошибка "%s"' % e)
    finally:
        wbooks.Close()
        app.Quit()

Офлайн

#5 Июль 23, 2016 10:15:16

Oleg_p
Зарегистрирован: 2014-10-15
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

win32com и excel даты

И пример файла :

Прикреплённый файлы:
attachment Лист Microsoft Excel.xlsx (8,8 KБ)

Офлайн

#6 Июль 23, 2016 13:49:45

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

win32com и excel даты

Oleg_p
отказаться пока не получится, т.к. в работе подавляющее большинство используют excel,
Очень даже получится. Рекомендую иметь дело с экселом только при чтении и записи.

Вам наверное надо использовать более высокоуровневые интерфейсы если вы планируете работать с данными. Я не обнаружил никаких проблем с чтением. Да часть строк содержит невалидные даты.

 import pandas as pd
xl = pd.ExcelFile("a.xlsx")
df = xl.parse(u"Лист1")
print np.array(df[u"Date"])
>>> 
[datetime.time(0, 0) datetime.datetime(2006, 2, 9, 0, 0)
 datetime.datetime(2005, 4, 4, 0, 0) datetime.datetime(2004, 12, 7, 0, 0)
 datetime.time(0, 0) datetime.datetime(2009, 6, 1, 0, 0)
 datetime.datetime(2009, 6, 1, 0, 0) datetime.datetime(2004, 8, 25, 0, 0)
 datetime.datetime(2004, 8, 25, 0, 0) datetime.datetime(2010, 8, 18, 0, 0)
 datetime.time(0, 0) datetime.datetime(2007, 2, 26, 0, 0)
 datetime.datetime(2010, 2, 1, 0, 0) datetime.time(0, 0)]
Oleg_p
отчеты репортить (так же в эксель).

На мой непросвященный взгляд чем раньше вы откажатесь от этой идеи (репотить в эксель) тем лучше будет всем.
Если я вас правильно понял вы делаете отчет. Это неизменяемый документ, доступный на множестве платформ, зачастую с очень специфическим форматом представления данных (требования гостов и нормативных документов к полям отступам абзацам форматам представления чисел и т.п.).

Для этой цели подходят pdf, html но никак не xlsx формат и инструментарий.
Мы например не морочимся и компилируем pdf отчеты латехом.



Отредактировано doza_and (Июль 23, 2016 14:01:35)

Офлайн

#7 Сен. 21, 2016 20:04:44

Oleg_p
Зарегистрирован: 2014-10-15
Сообщения: 6
Репутация: +  0  -
Профиль   Отправить e-mail  

win32com и excel даты

Всем привет!
Спасибо большое за помощь в решении вопроса.
Худо бедно получилось разобраться с типами в екселе, но по мере возможности буду отказываться от него в повседневке.
Далее итоговый скрипт (правда кривой, но может кому пригодится)

 class Excel_data(object):
    def time_correct(self, times):
        # корректируем нулевые даты excel в файлах
        time_zero = datetime.datetime(1899, 12, 30, 0, 0, 0)
        if float(times) == 0:
            return None
        else:
            d_t = time_zero + datetime.timedelta(days=float(times))
            d_t = d_t.date()
            return d_t.isoformat()
    def connect_oledb(self, path_file, xl_sheet):
        # подключение, вытягиваем данные из excel
        connection = win32com.client.Dispatch(u'ADODB.Connection')
        recordset = win32com.client.Dispatch(u'ADODB.Recordset')
        xl_sheet += u'$'
        DSN = u'PROVIDER=Microsoft.ACE.OLEDB.12.0;' \
              u'DATA SOURCE=' + path_file + u';Extended Properties="Excel 12.0 Xml;HDR=Yes;IMEX=1"'
        connection.Open(DSN)
        try:
            recordset.Open(u'SELECT * FROM [%s]'% xl_sheet, connection)
            data = zip(*recordset.GetRows())
            data_2 = []
            data_3 = []
            for i in data:
                for r in i:
                    # выявляем даты, если не корректные правим
                    if type(r) is type(pywintypes.Time(0)): r = self.time_correct(r)
                    data_2.append(r)
                data_2.insert(0, rep_date)
                # если полей меньше конечной таблицы
                if len(data_2) < 206:
                    while len(data_2) <= 205:
                        data_2.insert(-1, '')
                    data_3.append(data_2)
                    data_2 = []
            return data_3
        except Exception, e:
            print e
        if recordset is True: recordset.Close()
        del recordset
        if connection is True: connection.Close()
        del connection

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version