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 InsertRowWithJSON(json_str): """ 插入行 """ data = json.loads(json_str) InsertRow(data["location_bookmark_name"], data["data"], data["start_row_index"]) def InsertRow(location_bookmark_name, data, start_row_index=-1): """ 表格插入行 Args: location_bookmark_name: 用于定位表格的书签 data: 二维数组,用于填充表格数据 start_row_index: 起始行位置,默认为-1,即在表格末尾插入 """ doc = XSCRIPTCONTEXT.getDocument() tables = doc.getTextTables() bookmarks = doc.getBookmarks() bookmark_in_table_position = QueryBookmarkPositionInTable(tables, bookmarks) if location_bookmark_name not in bookmark_in_table_position: raise ValueError(f"未找到书签 {location_bookmark_name} 对应的表格") handle_table_index = bookmark_in_table_position[location_bookmark_name]["tableIndex"] 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: row_count = handle_table.getRows().getCount() rows_to_insert = len(data) if rows_to_insert > 0: # 确定插入位置 if start_row_index != -1 and 0 <= start_row_index < row_count: insert_pos = start_row_index + 1 # 在指定行下方插入 else: insert_pos = row_count # 插入到表格末尾 # 批量插入所有新行 handle_table.getRows().insertByIndex(insert_pos, rows_to_insert) # 填充数据到新插入的行 for data_row_idx, row_data in enumerate(data): target_row = insert_pos + data_row_idx # 计算目标行索引 for col_idx, cell_value in enumerate(row_data): cell = handle_table.getCellByPosition(col_idx, target_row) cell.setString(str(cell_value)) except Exception as e: raise RuntimeError(f"插入行时发生错误: {str(e)}") def BatchInsertRow(data_array): """ 批量插入行 """ doc = XSCRIPTCONTEXT.getDocument() tables = doc.getTextTables() bookmarks = doc.getBookmarks() bookmark_in_table_position = QueryBookmarkPositionInTable(tables, bookmarks) for arr_obj in data_array: location_bookmark_name = arr_obj.get('location_bookmark_name') data = arr_obj.get('data') start_row_index = arr_obj.get('start_row_index', -1) # 默认值为 -1 if location_bookmark_name not in bookmark_in_table_position: raise ValueError(f"未找到书签 {location_bookmark_name} 对应的表格") handle_table_index = bookmark_in_table_position[location_bookmark_name]["tableIndex"] 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: row_count = handle_table.getRows().getCount() rows_to_insert = len(data) if rows_to_insert > 0: # 确定插入位置 if start_row_index != -1 and 0 <= start_row_index < row_count: insert_pos = start_row_index + 1 # 在指定行下方插入 else: insert_pos = row_count # 插入到表格末尾 # 批量插入所有新行 handle_table.getRows().insertByIndex(insert_pos, rows_to_insert) # 填充数据到新插入的行 for data_row_idx, row_data in enumerate(data): target_row = insert_pos + data_row_idx # 计算目标行索引 for col_idx, cell_value in enumerate(row_data): cell = handle_table.getCellByPosition(col_idx, target_row) cell.setString(str(cell_value)) except Exception as e: raise RuntimeError(f"插入行时发生错误: {str(e)}") def InsertRowWithJSONDefineCol(json_str): """ 插入行 """ def DebugCallInsertRow(): """ 调试调用 """ InsertRow("t1", [["1", "2"], ["4", "5"]], 0) def DeleteRowWithJSON(json_str): """ 删除行 """ data = json.loads(json_str) DeleteRow(data["location_bookmark_name"], data["start_row_index"], data["delete_row_count"]) def DeleteRow(location_bookmark_name, start_row_index, delete_row_count=-1): """ 删除表格行 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() bookmarks = doc.getBookmarks() bookmark_in_table_position = QueryBookmarkPositionInTable(tables, bookmarks) if location_bookmark_name not in bookmark_in_table_position: raise ValueError(f"未找到书签 {location_bookmark_name} 对应的表格") handle_table_index = bookmark_in_table_position[location_bookmark_name]["tableIndex"] 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 or delete_row_count == -1: delete_row_count = row_count - start_row_index 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 ReplaceTextAndInsertTableRow(json_str): """ 替换文本和表格 """ data = json.loads(json_str) Replace(data["text"]) BatchInsertRow(data["table"]) def returnWithJSON(data): return json.dumps(data, ensure_ascii=False) g_exportedScripts = ( Replace, ReplaceWithJSON, QueryAll, QueryAllWithJSON, InsertRow, InsertRowWithJSON, DeleteRow, DeleteRowWithJSON, ReplaceTextAndInsertTableRow, DebugCallReplace, DebugCallReplaceList, DebugCallInsertRow, DebugCallDeleteRow, DebugCallLocateBookmarkLo1, DebugCallLocateBookmarkLo2, DebugCallInsertBookmark, DebugCallUpdateBookmark, DebugCallDeleteBookmark )