Как написать список вложенных элементов смешанного типа в документе Google с помощью API Документов Google (Python)?

Мой первый пост здесь. Заранее прошу прощения, если случайно нарушу какие-либо правила.

Предпосылки:

Предположим, что я создал учетную запись службы Google и получил файл учетных данных (JSON). Я создал документ Google, и у меня есть его doc_ID. Мой язык программирования — Python.

Проблема:

Предположим, что у меня есть список элементов смешанного типа, например. (обычный текст, несколько вложенных элементов списка, обычный текст, еще один вложенный элемент списка) и т. д. См. пример ниже:

my_list = [
    "This is the normal text line, without any itemized list format.",
    "* This is the outermost list item (number)",
    "* This is another outermost list item (number)",
    "  * This is a first-level indented list item (alpha)",
    "    * This is a second-level indented list item (roman)",
    "    * This is another second-level indented list item (roman)",
    "  * This is another first-level indented list item (alpha)",
    "This is the normal text line, without any itemized list format.",
    "* This is one more outermost list item (number)",
]

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

Я попробовал несколько подходов и получил максимально близкий результат, воспользовавшись предложением @tanaike в следующем посте. Как сделать отступ в маркированном списке с помощью API Документов Google

Вот мой пример кода:

    text_insert = ""
    for text in my_list:
        if text.startswith('* '):
            text_insert += text[2:] + '\n'
        elif text.startswith('  * '):
            text_insert += '\t' + text[4:] + '\n'
        elif text.startswith('    * '):
            text_insert += '\t\t' + text[6:] + '\n'
        else:
            text_normal = text + '\n'
            text_insert += text_normal
            end_index_normal = start_index + len(text_insert) + 1 - indent_corr
            start_index_normal = end_index_normal - len(text_normal)

    end_index = start_index + len(text_insert) + 1

    indented_requests = [
        {
            "insertText": {
                "text": text_insert,
                'location': {'index': start_index},
            }
        },
        {
            "createParagraphBullets": {
                'range': {
                    'startIndex': start_index,
                    'endIndex': end_index,  # Add 2 for the newline character
                },
                "bulletPreset": "NUMBERED_DECIMAL_ALPHA_ROMAN",
            }
        },
        {
            "deleteParagraphBullets": {
                'range': {
                    'startIndex': start_index_normal,
                    'endIndex': end_index_normal,
                },
            }
        },
    ]

    try:
        u_service.documents().batchUpdate(documentId=doc_id, body = {'requests': indented_requests}).execute()
    except HttpError as error:
        print(f"An error occurred: {error}")

В моем документе Google я получаю следующее:

Однако моя цель следующая (полученная после ручного редактирования):

Как я могу этого добиться? Любая помощь будет оценена.

Предупреждение: «Документ Google» = «Кошмар»

Sam Ginrich 27.05.2024 21:47
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
1
75
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Точки модификации:

  • В вашем сценарии показа end_index_normal и start_index_normal перезаписываются другим циклом.
  • В случае deleteParagraphBullets выбирается только один символ.
  • Кроме того, я догадался, что в вашей ситуации последний символ может не обязательно включаться в createParagraphBullets.

Когда эти моменты будут отражены в вашем сценарии, как насчет следующей модификации?

Модифицированный скрипт:

# Please set your variables.
doc_id = "###"
start_index = 1
indent_corr = 1


my_list = [
    "This is the normal text line, without any itemized list format.",
    "* This is the outermost list item (number)",
    "* This is another outermost list item (number)",
    "  * This is a first-level indented list item (alpha)",
    "    * This is a second-level indented list item (roman)",
    "    * This is another second-level indented list item (roman)",
    "  * This is another first-level indented list item (alpha)",
    "This is the normal text line, without any itemized list format.",
    "* This is one more outermost list item (number)",
]
text_insert = ""
deleteParagraphBullets = []
for text in my_list:
    if text.startswith('* '):
        text_insert += text[2:] + '\n'
    elif text.startswith('  * '):
        text_insert += '\t' + text[4:] + '\n'
    elif text.startswith('    * '):
        text_insert += '\t\t' + text[6:] + '\n'
    else:
        text_normal = text + '\n'
        text_insert += text_normal
        end_index_normal = start_index + len(text_insert) + 1 - indent_corr
        start_index_normal = end_index_normal - len(text_normal)
        deleteParagraphBullets.append({
            "deleteParagraphBullets": {
                'range': {
                    'startIndex': start_index_normal,
                    'endIndex': start_index_normal + 1,
                },
            }
        })
deleteParagraphBullets.reverse()
indented_requests = [
    {
        "insertText": {
            "text": text_insert,
            'location': {'index': start_index},
        }
    },
    {
        "createParagraphBullets": {
            'range': {
                'startIndex': start_index,
                'endIndex': start_index + len(text_insert),
            },
            "bulletPreset": "NUMBERED_DECIMAL_ALPHA_ROMAN",
        }
    }
] + deleteParagraphBullets
u_service.documents().batchUpdate(documentId=doc_id, body = {'requests': indented_requests}).execute()

Тестирование:

При запуске этого сценария получается следующий результат.

От

К

Использованная литература:

Идеальный! Работает безупречно! Всего один вопрос: Какова цель deleteParagraphBullets.reverse()? Я также попробовал не реверсировать его, и он все равно дает тот же результат. Я хотел бы принять это как ответ, но моя репутация 11 мне не позволяет.

Ait Paca 28.05.2024 10:54

Дополнительный вопрос: этот подход подготавливает одну текстовую строку из всех заданных элементов списка (в настоящее время только двух форматов: элемент списка и обычный текст), а затем подготавливает запрос. Если в списке есть несколько типов элементов, можем ли мы подготовить отдельный запрос для каждого элемента в цикле for, а затем объединить все в конце, чтобы сделать один единственный запрос? Простой первоначальный подход дает нумерацию всех отступов только самыми крайними номерами (без поднумерации).

Ait Paca 28.05.2024 11:00

@Ait Paca О deleteParagraphBullets.reverse(), в случае удаления маркеров, когда оно выполняется в порядке возрастания, индексы других частей изменяются. Итак, я использовал порядок убывания.

Tanaike 28.05.2024 13:35

@Ait Paca Что касается твоего нового вопроса, я хотел бы тебя поддержать. Но вопрос ответа — это новый вопрос, и он отличается от вашего вопроса. Так можете ли вы опубликовать это как новый вопрос? Потому что, когда ваш первоначальный вопрос изменяется комментарием, другие пользователи, которые видят ваш вопрос, приходят в замешательство. Опубликовав его как новый вопрос, пользователи, включая меня, смогут подумать об этом. Если вы можете помочь решить вашу новую проблему, я буду рад. Можете ли вы сотрудничать, чтобы решить ваш новый вопрос?

Tanaike 28.05.2024 13:35

Спасибо большое за решение и объяснение. Я принял ваш ответ как правильный (ранее мой комментарий был принят за голосование «за», что мне не разрешено на данном этапе репутации). Я опубликую новый вопрос о конструкции цикла for.

Ait Paca 28.05.2024 14:18

@Ait Paca Спасибо за ответ. Я понимаю вашу текущую ситуацию. И когда я увидел ваш новый вопрос, я хотел бы его проверить. И тебе спасибо.

Tanaike 28.05.2024 14:23

Большое спасибо! Я только что опубликовал свой вопрос, который доступен по адресу stackoverflow.com/q/78544321/25276165. С нетерпением жду вашего совета/помощи.

Ait Paca 28.05.2024 15:11

@Ait Paca Спасибо за ответ. Я проверю. Если у меня возникнет вопрос, я опубликую его в вашем новом вопросе.

Tanaike 29.05.2024 00:50

Другие вопросы по теме