Форум программистов, компьютерный форум, киберфорум
nekit270
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
Добро пожаловать, здесь я программирую бессмысленно и беспощадно

Чтение из XLSX-файла с помощью Python

Запись от nekit270 размещена 11.12.2023 в 02:42
Показов 1945 Комментарии 0
Метки excel, python, xlsx

Вдохновившись этой статейкой от sqltd1, решил написать на питончике скрипт для чтения данных из ячейки XLSX-файла.

Но не просто написать скрипт, а сделать это без внешних библиотек и всего прочего.


Формат XLSX

XLSX представляет собой zip-архив. Для извлечения значений нужны два файла из него:
/xl/worksheets/<лист>.xml - собственно лист
/xl/sharedStrings.xml - строки


Извлечение значений

Для распаковки использую модуль zipfile, а в качестве простенького XML-парсера подойдут регулярные выражения.

Код класса (42 строки, поэтому под спойлером):
Кликните здесь для просмотра всего текста

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import zipfile, re
 
class XlsxReader:
    __worksheet = None
    __strings = []
 
    def __init__(self, file, worksheet):
        # Открытие XLSX-файла как ZIP-архива
        with zipfile.ZipFile(file) as zip:
            # Чтение файла листа из архива
            self.__worksheet = zip.read(f'xl/worksheets/{worksheet}.xml').decode('utf-8')
 
            # Чтение файла хранилища строк из архива
            strings_file = zip.read('xl/sharedStrings.xml').decode('utf-8')
 
            # Добавление строк в список
            for match in re.finditer('\\<si\\>\\<t\\>([^\\<]+)\\</t\\>\\</si\\>', strings_file):
                self.__strings.append(match.group(1))
 
    def read(self, cell):
        # Если в документе есть строковые значения
        if len(self.__strings) > 0:
            # Поиск элемента <c r="ячейка" t="s"><v>индекс</v></c>
            s_match = re.search(f'\\<c r="{cell}" t="s"\\>\\<v\\>([^\\<]+)\\</v\\>\\</c\\>', self.__worksheet)
 
            # Если элемент найден
            if(s_match != None and len(s_match.groups()) > 0):
                # Найти строку в списке по индексу и вернуть
                return self.__strings[int(s_match.group(1))]
 
        # В документе нет строковых значений
 
        # Поиск элемента <c r="ячейка"><v>значение</v></c>
        n_match = re.search(f'\\<c r="{cell}"\\>\\<v\\>([^\\<]+)\\</v\\>\\</c\\>', self.__worksheet)
 
        # Если элемент найден
        if(n_match != None and len(n_match.groups()) > 0):
            # Вернуть его
            return n_match.group(1)
        
        # Если ничего не найдено, вернуть None
        return None


Пример использования:
Python
1
2
3
4
5
6
7
from xlsx_reader import XlsxReader
 
reader = XlsxReader('test.xlsx', 'sheet1')
print('A1', reader.read('A1'))
print('B2', reader.read('B2'))
print('B8', reader.read('B8'))
print('D6', reader.read('D6'))
Тестировал я на этом файле:
Нажмите на изображение для увеличения
Название: Снимок экрана 2023-12-11 022747.png
Просмотров: 209
Размер:	8.6 Кб
ID:	8395
test.xlsx

Результат:
Code
1
2
3
4
A1 5
B2 92
B8 String2
D6 TestString

Версия без комментариев (для пущей экономии места и использования в качестве библиотеки):
Кликните здесь для просмотра всего текста

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import zipfile, re
 
class XlsxReader:
    __worksheet = None
    __strings = []
 
    def __init__(self, file, worksheet):
        with zipfile.ZipFile(file) as zip:
            self.__worksheet = zip.read(f'xl/worksheets/{worksheet}.xml').decode('utf-8')
 
            strings_file = zip.read('xl/sharedStrings.xml').decode('utf-8')
 
            for match in re.finditer('\\<si\\>\\<t\\>([^\\<]+)\\</t\\>\\</si\\>', strings_file):
                self.__strings.append(match.group(1))
 
    def read(self, cell):
        if len(self.__strings) > 0:
            s_match = re.search(f'\\<c r="{cell}" t="s"\\>\\<v\\>([^\\<]+)\\</v\\>\\</c\\>', self.__worksheet)
 
            if(s_match != None and len(s_match.groups()) > 0):
                return self.__strings[int(s_match.group(1))]
 
        n_match = re.search(f'\\<c r="{cell}"\\>\\<v\\>([^\\<]+)\\</v\\>\\</c\\>', self.__worksheet)
 
        if(n_match != None and len(n_match.groups()) > 0):
            return n_match.group(1)
        
        return None


Внимание! Даже если тип значения в XLSX-файле - не строка, возвращено будет значение типа str. Это сделано специально, чтобы вызывающий мог сам конвертировать его в нужный тип числа.

P.S. Обратите внимание, что, к примеру, "Лист 1" называется "sheet1" внутри XLSX-файла. Использовать нужно именно "внутреннее" название.
Метки excel, python, xlsx
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru