Форум сайта python.su
0
Господа,есть работающий код:
#работа с файлом excel import pandas as pd from pandas import DataFrame read_table = pd.read_excel(r'D:\ОБУЧЕНИЕ\py\gtt.xlsx') df = DataFrame(read_table) #работа с БД access import pyodbc connStr = pyodbc.connect( r'Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=D:\ОБУЧЕНИЕ\py\svod.mdb;') #вставляем данные cursor = connStr.cursor() for index,\ row in df.iterrows(): cursor.execute("INSERT INTO [D:\ОБУЧЕНИЕ\py\svod.mdb].set ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11]) values (?,?,?,?,?,?,?,?,?,?,?)" , row[1],row[2],row[3],row[4],row[5],row[6],row[7],row[8],row[9],row[10],row[11]) connStr.commit() cursor.close() connStr.close()
Офлайн
27
Вместо
cursor.execute("INSERT INTO [D:\ОБУЧЕНИЕ\py\svod.mdb].set ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11]) values (?,?,?,?,?,?,?,?,?,?,?)" , row[1],row[2],row[3],row[4],row[5],row[6],row[7],row[8],row[9],row[10],row[11])
[code python]cursor.execute("INSERT INTO [D:\ОБУЧЕНИЕ\py\svod.mdb].set ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11]) values (?,?,?,?,?,?,?,?,?,?,?)"
, *row)[/code]stolbci = '' for ii in range(1,len(row) + 1): stolbci += '[{}],'.format(ii) stolbci = stolbci[:-1] # print(stolbci) voprosi = ('?,'*len(row))[:-1] # print(voprosi) db = 'D:\ОБУЧЕНИЕ\py\svod.mdb' zapros = "INSERT INTO [{}].set ({}) values ({})".format(db, stolbci, voprosi) cursor.execute(zapros, *row)
row = row[1:]
Отредактировано Rafik (Дек. 6, 2018 14:37:07)
Офлайн
0
Спасибо!
cursor = connStr.cursor() for index,\ row in df.iterrows(): stolbci = '' for ii in range(1, len(row) + 1): stolbci += '[{}],'.format(ii) stolbci = stolbci[:-1] print(stolbci) voprosi = ('?,' * len(row))[:-1] print(voprosi) db = 'D:\ОБУЧЕНИЕ\py\svod.mdb' zapros = "INSERT INTO [{}].set ({}) values ({})".format(db, stolbci, voprosi) cursor.execute(zapros, *row)
cursor.execute(zapros, row)
pyodbc.ProgrammingError: ('The SQL contains 41 parameter markers, but 1 parameters were supplied', 'HY000')
Отредактировано sevlovan (Дек. 6, 2018 16:14:02)
Офлайн
27
Звездочка перед row значит, что row передается в функцию в распакованном виде, т.е как бы много параметров, столько, сколько элементов в row. Например:
row = (1,2,4,'a') func(*row) # эквивалентна func(1,2,4,'a') # То же самое, что и func(row[0], row[1], row[2], row[3])
sevlovanтребуется 41 параметр, а передаётся только один.
pyodbc.ProgrammingError: ('The SQL contains 41 parameter markers, but 1 parameters were supplied', ‘HY000’)
Отредактировано Rafik (Дек. 6, 2018 19:30:25)
Офлайн
0
Спасибо, уважаемый!
Все доходчиво и продуктивно. Помогли!
Отредактировано sevlovan (Дек. 6, 2018 20:52:51)
Офлайн
0
Rafik
Добрый день!
в продолжение темы: в файле excel у меня данные разного типа: и дата и текст и числа…
в ms access (2010) в таблице все поля сделал memo (ну чтобы наверняка все вошло), но не входит..вот что пишет:
cursor.execute(zapros, *row) pyodbc.DataError: ('22008', '[22008] [Microsoft][Драйвер ODBC Microsoft Access]Переполнение поля даты и времени (36) (SQLParamData)')
Офлайн
27
Есть два варианта: либо все данные в excell причесать привести к общему виду, либо в питоне проверять тип входных данных, полученных из excell и, если тип не соответствует, преобразовать их к тому виду, который принимает access.
Для приведения к общему виду в excell можно провести замену неправильных разделителей в столбце с датой-временем на правильные и назначение правильного формата ячейки для этого столбца. Этот процесс возможно получится записать в макрос. Если таблица постоянно пополняется, то может быть получится сделать небольшой макрос для excell, который будет проверять корректность ввода и исправлять ошибки. На либреофис такой фокус возможен. Вешается макрос на “Содержимое изменено” в событиях листа
Дату-время желательно хранить в БД в формате дата-время. В дальнейшем будет проще писать запросы с использованием фильтров и вычислений с датой-временем.
Офлайн
0
Rafik
Дату-время желательно хранить в БД в формате дата-время. В дальнейшем будет проще писать запросы с использованием фильтров и вычислений с датой-временем.Я планировал сначала записать все данные в мемо а потом поменять тип данных на приемлемый для построения запросов и отчетов.
либо в питоне проверять тип входных данных, полученных из excell и, если тип не соответствует, преобразовать их к тому виду, который принимает access.но как..?
Отредактировано sevlovan (Дек. 11, 2018 15:46:30)
Офлайн
27
Я не работал с pandas и уровень общения с excell файлами ограничивается старым форматом xls, который читаю с помощью xlrd. Для новых форматов 2010 (xlsx) требуется библитека openpyxl. Это не важно.
Перейдём к нашим баранам, т.е. упрямым и некорректным данным.
Перво-наперво надо будет посмотреть как выглядят корректные данные, которые принимает access. Именно как выглядит содержимое корректной ячейки после прочтения pandas-ом.
Собрать максимальное количество всевозможных уникальных образцов данных, которые не соответствуют правильному шаблону.
Первый образец уже есть
sevlovanЭто можно разбить с помощью метода split() по пробелу, взять последний элемент и привести, например, к виду 12-01-2017 с помощью метода replace()
“от 12.01.2017”
cell_value = 'от 12.01.2017' print(cell_value.split(' ')[-1].replace('.', '-'))
Офлайн
0
Rafik, добрый вечер!
мне тут подсказали, что эффективней мою задачу можно решить методом: xls –> csv –> mdb
вот мое новое “творчество”, наглым образом скопипащенное со stackoverflow и адаптированное под мои нужды:
import xlrd import csv import os import pyodbc with xlrd.open_workbook('D:\ОБУЧЕНИЕ\py\gtt.xls') as wb: sh = wb.sheet_by_index(0) with open('gtt.csv', 'w', newline="") as f: c = csv.writer(f) for r in range(sh.nrows): c.writerow(sh.row_values(r)) with open('D:\ОБУЧЕНИЕ\py\gtt.csv', 'r') as reader, open('D:\ОБУЧЕНИЕ\py\gtt_clean.csv', 'w') as writer: read_csv = csv.reader(reader); write_csv = csv.writer(writer, lineterminator='\n') for line in read_csv: if len(line[1]) > 0: write_csv.writerow(line) access_path = "D:\ОБУЧЕНИЕ\py\\svod.mdb" con = pyodbc.connect("DRIVER={{Microsoft Access Driver (*.mdb, *.accdb)}};DBQ={};" \ .format(access_path)) strSQL = "SELECT * INTO [set_s] FROM [text;HDR=Yes;FMT=Delimited(,);" + \ "Database=D:\ОБУЧЕНИЕ\py].gtt_clean.csv;" cur = con.cursor() cur.execute(strSQL) con.commit()
from glob import glob g = glob('*.xls') for fname in glob
Отредактировано sevlovan (Дек. 13, 2018 16:39:05)
Офлайн