Python xlsxwriter извлекает значение из ячейки

Можно ли извлечь данные, которые я записал в xlsxwriter.worksheet?

import xlsxwriter

output = "test.xlsx"
workbook = xlsxwriter.Workbook(output)
worksheet = workbook.add_worksheet()


worksheet.write(0, 0, 'top left')
if conditional:
    worksheet.write(1, 1, 'bottom right')

for row in range(2):
  for col in range(2):
    # Now how can I check if a value was written at this coordinate?
    # something like worksheet.get_value_at_row_col(row, col)

workbook.close()

person Heinrich    schedule 12.07.2020    source источник


Ответы (2)


Можно ли извлечь данные, которые я записал в xlsxwriter.worksheet?

Нет. XlsxWriter предназначен только для записи. Если вам нужно отслеживать свои данные, вам нужно будет делать это в своем собственном коде, за пределами XlsxWriter.

person jmcnamara    schedule 12.07.2020
comment
Хотя я согласен с тем, что отслеживать ваши данные в вашем коде проще всего, я думаю, что ответы с создателем xlsxwriter в ответе @Franz будут полезны наряду с этим. - person Rafael Zayas; 27.05.2021

Можно ли извлечь данные, которые я записал в xlsxwriter.worksheet?

Да. Несмотря на то, что XlsxWriter предназначен только для записи, он сохраняет значения таблицы во внутренней структуре и записывает их в файл только при выполнении workbook.close().

Каждый рабочий лист имеет атрибут table. Это словарь, содержащий записи для всех заполненных строк (номера строк, начинающиеся с 0, являются ключами). Эти записи снова являются словарями, содержащими записи для всех заполненных ячеек в строке (номера столбцов, начинающиеся с 0, являются ключами).

Таким образом, table[row][col] даст вам запись в нужной позиции (но только в том случае, если запись есть, иначе не получится).

Обратите внимание, что эти записи по-прежнему являются не текстом, числом или формулой, которые вы ищете, а именованными кортежами, которые также содержат формат ячейки. Вы можете ввести проверку записей и извлечь содержимое в зависимости от их характера. Вот возможные результаты type(entry) и поля именованных кортежей, которые доступны:

  • xlsxwriter.worksheet.cell_string_tuple: строка, формат
  • xlsxwriter.worksheet.cell_number_tuple: номер, формат
  • xlsxwriter.worksheet.cell_blank_tuple: формат
  • xlsxwriter.worksheet.cell_boolean_tuple: логическое значение, формат
  • xlsxwriter.worksheet.cell_formula_tuple: формула, формат, значение
  • xlsxwriter.worksheet.cell_arformula_tuple: формула, формат, значение, диапазон

Для чисел, логических значений и формул доступ к содержимому можно получить, прочитав соответствующее поле именованного кортежа.

Для формул массива содержимое присутствует только в верхней левой ячейке выходного диапазона, а остальные ячейки представлены числовыми элементами со значением 0.

Со строками дело обстоит сложнее, так как в концепции хранения Excel используется общая таблица строк, а отдельные записи ячеек указывают только на индекс этой таблицы. Доступ к таблице общих строк можно получить как атрибут str_table.string_table рабочего листа. Это словарь, где ключами являются строки, а значениями являются связанные индексы. Чтобы получить доступ к строкам по индексу, вы можете создать отсортированный список из словаря следующим образом:

shared_strings = sorted(worksheet.str_table.string_table, key=worksheet.str_table.string_table.get)

Я расширил ваш пример сверху, чтобы включить все объясненные функции. Теперь это выглядит так:

import xlsxwriter

output = "test.xlsx"
workbook = xlsxwriter.Workbook(output)
worksheet = workbook.add_worksheet()

worksheet.write(0, 0, 'top left')
worksheet.write(0, 1, 42)
worksheet.write(0, 2, None)
worksheet.write(2, 1, True)
worksheet.write(2, 2, '=SUM(X5:Y7)')
worksheet.write_array_formula(2,3,3,4, '{=TREND(X5:X7,Y5:Y7)}')
worksheet.write(4,0, 'more text')
worksheet.write(4,1, 'even more text')
worksheet.write(4,2, 'more text')
worksheet.write(4,3, 'more text')

for row in range(5):
  row_dict = worksheet.table.get(row, None)
  for col in range(5):
    if row_dict != None:
      col_entry = row_dict.get(col, None)
    else:
      col_entry = None
    print(row,col,col_entry)

shared_strings = sorted(worksheet.str_table.string_table, key=worksheet.str_table.string_table.get)

print()
if type(worksheet.table[0][0]) == xlsxwriter.worksheet.cell_string_tuple:
  print(shared_strings[worksheet.table[0][0].string])

# type checking omitted for the rest...
print(worksheet.table[0][1].number)
print(bool(worksheet.table[2][1].boolean))
print('='+worksheet.table[2][2].formula)
print('{='+worksheet.table[2][3].formula+'}')

workbook.close()
person Franz    schedule 04.08.2020
comment
Я автор XlsxWriter. Это хорошая часть обратного проектирования или доказательства концепции, но я бы не советовал делать это на практике. Нет никакой явной или неявной гарантии того, что данные сохраняются или будут поддерживаться после того, как они перейдут через API XlsxWriter. Лучший способ справиться с такими вариантами использования — отслеживать данные за пределами библиотеки. Python имеет богатый инструментарий для обработки данных, который лучше, чем полагаться на внутренние компоненты библиотеки, которая не была написана для целей отслеживания данных. - person jmcnamara; 04.08.2020
comment
Позвольте мне сказать спасибо за такой удобный модуль Python, XlsxWriter действительно мне очень помогает! Я абсолютно согласен, что в целом отслеживать ваши данные намного проще вне XlsxWriter. Я просто наткнулся на эти внутренности, когда искал решение для автоподбора ширины столбца, которое не требует постоянного внимания при заполнении таблицы... (В этом ответе, если быть точным: stackoverflow.com/a/53091320). - person Franz; 04.08.2020
comment
Более безопасным, хотя, вероятно, и более подробным способом решения этой проблемы было бы наследование и переопределение класса рабочего листа по умолчанию и добавление некоторого кода автоподбора, как в этом примере: xlsxwriter.readthedocs.io/example_inheritance2.html - person jmcnamara; 05.08.2020