From 0385e63e6e29bcb1f698fa54368a7d7a00d34fca Mon Sep 17 00:00:00 2001 From: zzs Date: Mon, 24 Mar 2025 11:49:58 +0800 Subject: [PATCH] fix: insert bookmark error --- BookmarkExec.py | 5 +- BookmarkOP.py | 432 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 434 insertions(+), 3 deletions(-) create mode 100644 BookmarkOP.py diff --git a/BookmarkExec.py b/BookmarkExec.py index 29d0592..e1f16cf 100644 --- a/BookmarkExec.py +++ b/BookmarkExec.py @@ -66,7 +66,7 @@ def DebugCallReplaceList(): Replace({"list": "1\r2\r3\r4"}) -def QueryAll(): +def QueryAll(inner_call=False): """ 查询所有书签,表格中的书签获取对应表格index @@ -177,7 +177,7 @@ def InsertRow(location_bookmark_name, data, start_row_index=-1): data: 二维数组,用于填充表格数据 start_row_index: 起始行位置,默认为-1,即在表格末尾插入 """ - bookmark_info = QueryAll() + bookmark_info = QueryAll(inner_call=True) table_bookmarks = bookmark_info["table"] handle_table_index = FindTableIndex(table_bookmarks, location_bookmark_name) @@ -409,7 +409,6 @@ def CreateTable(location_bookmark_name, data): data: 二维数组,用于填充表格数据 """ - g_exportedScripts = ( Replace, ReplaceWithJSON, diff --git a/BookmarkOP.py b/BookmarkOP.py new file mode 100644 index 0000000..e0e3a98 --- /dev/null +++ b/BookmarkOP.py @@ -0,0 +1,432 @@ +import json +import time + +def ReplaceOne(bookmark_obj_collection, bookmark_name, new_value): + """ + 替换一个书签 + Args: + bookmark_obj_collection: 书签对象集合 + bookmark_name: 书签名称 + new_value: 新值 + """ + + if bookmark_obj_collection.hasByName(bookmark_name): + bookmark = bookmark_obj_collection.getByName(bookmark_name) + anchor = bookmark.getAnchor() + anchor.setString(new_value) + + +def ReplaceAll(bookmark_obj_collection, bookmark_name_value_map): + """ + 替换所有书签 + Args: + bookmark_obj_collection: 书签对象集合 + bookmark_name_value_map: 书签名称和新值的映射 + """ + + for bookmark_name, new_value in bookmark_name_value_map.items(): + ReplaceOne(bookmark_obj_collection, bookmark_name, new_value) + + +def Replace(bookmark_name_value_map): + """ + 替换所有书签 + Args: + bookmark_name_value_map: 书签名称和新值的映射 + """ + + doc = XSCRIPTCONTEXT.getDocument() + bookmarks = doc.getBookmarks() + ReplaceAll(bookmarks, bookmark_name_value_map) + + +def ReplaceWithJSON(json_str): + """ + 替换所有书签 + Args: + json_str: 书签名称和新值的映射的JSON字符串 + """ + + bookmark_name_value_map = json.loads(json_str) + Replace(bookmark_name_value_map) + + +def DebugCallReplace(): + """ + 调试调用 + """ + + Replace({"h1": "P1", "h2": "P2", "h3": "P3"}) + + +def DebugCallReplaceList(): + """ + 调试调用,替换list + """ + + Replace({"list": "1\r2\r3\r4"}) + +def QueryAll(): + """ + 查询所有书签,表格中的书签获取对应表格index + + 返回结果格式: + { + "text": [], + "table": [ + { + "tableIndex": 表格索引, + "bookmark": [书签名称列表] + } + ] + } + """ + + doc = XSCRIPTCONTEXT.getDocument() + bookmarks = doc.getBookmarks() + bookmark_names = bookmarks.getElementNames() + filtered_bookmarks = [bk_name for bk_name in bookmark_names if '_' not in bk_name and ':' not in bk_name] + result = {"text": [], "table": []} + + tables = doc.getTextTables() + bookmark_in_table_position = QueryBookmarkPositionInTable(tables, bookmarks) + + existing_table_indices = {} + + for bk_name in filtered_bookmarks: + if bk_name in bookmark_in_table_position: + table_index = bookmark_in_table_position[bk_name]["tableIndex"] + if table_index in existing_table_indices: + index = existing_table_indices[table_index] + result["table"][index]["bookmark"].append(bk_name) + else: + new_entry = {"tableIndex": table_index, "bookmark": [bk_name]} + result["table"].append(new_entry) + existing_table_indices[table_index] = ( + len(result["table"]) - 1 + ) # 更新索引记录 + else: + result["text"].append(bk_name) + + return result + + +def QueryAllWithJSON(): + return returnWithJSON(QueryAll()) + +def QueryBookmarkPositionInTable(tables, bookmarks): + """ + 查询书签在表格中的位置 + {'bk1': {'tableIndex': 0, 'row': 0, 'col': 0}, 'bk2': {'tableIndex': 0, 'row': 0, 'col': 2}} + """ + + bookmark_names = bookmarks.getElementNames() + + bookmark_position = {} + + for table_index in range(tables.getCount()): + table = tables.getByIndex(table_index) + + col_count = table.getColumns().getCount() + row_count = table.getRows().getCount() + + for row in range(row_count): + for col in range(col_count): + cell = table.getCellByPosition(col, row) + cell_text_obj = cell.getText() + + for bk_name in bookmark_names: + bookmark_obj = bookmarks.getByName(bk_name) + bookmark_text_obj = bookmark_obj.getAnchor().getText() + if cell_text_obj == bookmark_text_obj: + bookmark_position[bk_name] = { + "tableIndex": table_index, + "col": col, + "row": row, + } + + return bookmark_position + + +def CreateRow(table, row_count): + """ + 创建表格行 + """ + table.getRows().insertByIndex(table.getRows().getCount(), row_count) + + +def FindTableIndex(table_bookmarks, location_bookmark_name): + """ + 找到表格索引 + """ + handle_table_index = -1 + for table_info in table_bookmarks: + if location_bookmark_name in table_info["bookmark"]: + handle_table_index = table_info["tableIndex"] + break + + if handle_table_index == -1: + raise ValueError(f"未找到书签 {location_bookmark_name} 对应的表格") + return handle_table_index + + +def InsertRow(location_bookmark_name, data, start_row_index=-1): + """ + 表格插入行 + Args: + location_bookmark_name: 用于定位表格的书签 + data: 二维数组,用于填充表格数据 + start_row_index: 起始行位置,默认为-1,即在表格末尾插入 + """ + bookmark_info = QueryAll() + table_bookmarks = bookmark_info["table"] + + handle_table_index = FindTableIndex(table_bookmarks, location_bookmark_name) + + doc = XSCRIPTCONTEXT.getDocument() + tables = doc.getTextTables() + + try: + handle_table = tables.getByIndex(handle_table_index) + except IndexError: + raise IndexError(f"表格索引 {handle_table_index} 超出范围") + + col_count = handle_table.getColumns().getCount() + row_count = handle_table.getRows().getCount() + + if not data or len(data) == 0: + return + + if any(len(row) != col_count for row in data): + raise ValueError(f"数据列数不匹配,表格有 {col_count} 列") + + try: + for _ in range(len(data)): + if start_row_index > 0 & start_row_index < row_count: + handle_table.getRows().insertByIndex(start_row_index, 1) + else: + handle_table.getRows().insertByIndex(row_count, 1) + + for row_idx, row_data in enumerate(data, start=row_count): + for col_idx, cell_value in enumerate(row_data): + cell = handle_table.getCellByPosition(col_idx, row_idx) + cell.setString(str(cell_value)) + except Exception as e: + raise RuntimeError(f"插入行时发生错误: {str(e)}") + + +def DebugCallInsertRow(): + """ + 调试调用 + """ + InsertRow("h1", [["1", "2", "3"], ["4", "5", "6"]], 0) + + +def DeleteRow(location_bookmark_name, start_row_index, delete_row_count): + """ + 删除表格行 + + Args: + location_bookmark_name: 用于定位表格的书签 + start_row_index: 起始行位置(删除行包含本行) + delete_row_count: 删除的行数 + """ + bookmark_info = QueryAll() + table_bookmarks = bookmark_info["table"] + handle_table_index = FindTableIndex(table_bookmarks, location_bookmark_name) + + doc = XSCRIPTCONTEXT.getDocument() + tables = doc.getTextTables() + handle_table = tables.getByIndex(handle_table_index) + row_count = handle_table.getRows().getCount() + if start_row_index < 0 or start_row_index >= row_count: + raise ValueError(f"起始行索引 {start_row_index} 超出范围") + + if start_row_index + delete_row_count > row_count: + raise ValueError(f"删除行数量 {delete_row_count} 超出范围") + + try: + handle_table.getRows().removeByIndex(start_row_index, delete_row_count) + except Exception as e: + raise RuntimeError(f"删除行时发生错误: {str(e)}") + + +def DebugCallDeleteRow(): + """ + 调试调用 + """ + DeleteRow("h1", 1, 2) + + +def LocateBookmark(bookmark_name): + """ + 定位书签并选中内容 + Args: + bookmark_name: 要定位的书签名称 + """ + doc = XSCRIPTCONTEXT.getDocument() + + if False == doc.getBookmarks().hasByName(bookmark_name): + return + + bookmark = doc.getBookmarks().getByName(bookmark_name) + + try: + # 获取书签的文本范围锚点 + anchor = bookmark.getAnchor() + + # 获取文档控制器 + controller = doc.getCurrentController() + + # 将视图光标移动到书签位置并选中 + view_cursor = controller.getViewCursor() + view_cursor.gotoRange(anchor, False) # False表示不扩展选区 + + # 如果需要高亮显示(可选) + controller.select(anchor) + + # 确保窗口可见(针对隐藏窗口的情况) + try: + window = controller.getFrame().getContainerWindow() + window.setVisible(True) + window.toFront() + except Exception: + pass + + except Exception as e: + raise RuntimeError(f"定位书签失败: {str(e)}") from e + +def DebugCallLocateBookmarkLo1(): + LocateBookmark("lo1") + +def DebugCallLocateBookmarkLo2(): + LocateBookmark("lo2") + +def InsertBookmark(bookmark_name): + """ + 选中内容插入书签,如果没有选中任何内容,插入点书签 + Args: + bookmark_name: 要插入的书签名称 + """ + doc = XSCRIPTCONTEXT.getDocument() + controller = doc.getCurrentController() + + # 获取当前选区 + selection = controller.getSelection() + + # 检查是否已存在同名书签,如果存在则先删除 + bookmarks = doc.getBookmarks() + if bookmarks.hasByName(bookmark_name): + bookmarks.getByName(bookmark_name).dispose() + + try: + # 创建书签 + if selection.getCount() > 0: + # 尝试获取选区的第一个元素 + range_to_bookmark = selection.getByIndex(0) + + # 创建书签并附加到选区 + bookmark = doc.createInstance("com.sun.star.text.Bookmark") + bookmark.attach(range_to_bookmark) + bookmark.setName(bookmark_name) + else: + # 没有选中内容,创建点书签 + cursor = controller.getViewCursor() + text_cursor = cursor.getText().createTextCursorByRange(cursor) + + # 创建书签并附加到光标位置 + bookmark = doc.createInstance("com.sun.star.text.Bookmark") + bookmark.attach(text_cursor) + bookmark.setName(bookmark_name) + except Exception as e: + raise RuntimeError(f"插入书签失败: {str(e)}") from e + + + +def DebugCallInsertBookmark(): + """ + 调试调用 + """ + InsertBookmark("bookmark_" + str(time.time())) + + +def UpdateBookmark(bookmark_name, new_value): + """ + 修改书签名称(通过删除旧书签 + 插入新书签实现) + Args: + bookmark_name: 原书签名称 + new_value: 新书签名称 + """ + doc = XSCRIPTCONTEXT.getDocument() + bookmarks = doc.getBookmarks() + + if not bookmarks.hasByName(bookmark_name): + raise ValueError(f"书签 '{bookmark_name}' 不存在") + + if bookmarks.hasByName(new_value): + raise ValueError(f"书签 '{new_value}' 已存在") + + # 获取旧书签的锚点位置 + old_bookmark = bookmarks.getByName(bookmark_name) + old_bookmark.setName(new_value) + +def DebugCallUpdateBookmark(): + """ + 调试调用 + """ + UpdateBookmark("ole_bookmark", "new_bookmark") + +def DeleteBookmark(bookmark_name): + """ + 删除书签但保留内容(通过断开书签与锚点的关联) + """ + doc = XSCRIPTCONTEXT.getDocument() + bookmarks = doc.getBookmarks() + + if not bookmarks.hasByName(bookmark_name): + return + + bookmark = bookmarks.getByName(bookmark_name) + + if hasattr(bookmark, "Anchor"): + try: + anchor = bookmark.Anchor + anchor.getText().removeTextContent(bookmark) + except Exception as e: + pass + +def DebugCallDeleteBookmark(): + """ + 调试调用 + """ + DeleteBookmark("remove_me") + + +def CreateTable(location_bookmark_name, data): + """ + 创建表格 + Args: + location_bookmark_name: 用于定位表格的书签 + data: 二维数组,用于填充表格数据 + """ + +def returnWithJSON(data): + return json.dumps(data, ensure_ascii=False) + +g_exportedScripts = ( + Replace, + ReplaceWithJSON, + QueryAll, + QueryAllWithJSON, + InsertRow, + DeleteRow, + DebugCallReplace, + DebugCallReplaceList, + DebugCallInsertRow, + DebugCallDeleteRow, + DebugCallLocateBookmarkLo1, + DebugCallLocateBookmarkLo2, + DebugCallInsertBookmark, + DebugCallUpdateBookmark, + DebugCallDeleteBookmark +)