如何在 Microsoft Word 中移動圖片
學習如何在 Word 中拖曳圖片、選擇文字環繞方式、將圖片與段落保持在一起或將其固定在頁面上,以及如何解決圖片無法移動的問題。
LibreOffice Calc 巨集在處理大型工作表時經常會變慢,原因很簡單:巨集花在跨越 UNO 物件邊界上的時間比實際計算的時間要多。讀取一個儲存格、修改它、然後再寫回數千次,其開銷遠大於一次性移動更大區塊的相同資料。
目標並非抽像地追求每個宏的「速度」都「很快」。有效的最佳化應該在相同的資料集上產生相同的輸出,同時縮短運行時間,保持 Calc 的響應速度足以滿足工作流程的需求,並且避免引入新的正確性或記憶體問題。以下技巧著重於這些可衡量的結果。
截至 2026 年 10 月,LibreOffice SDK 文件已在 LibreOffice 26.8 API 參考中明確列出了此處使用的電子表格介面。這些核心方法是長期沿用的 UNO 接口,而非新引入的性能最佳化特性。
首先要建立一個可重複的基準。 LibreOffice Basic 提供了GetSystemTicks()一個功能,官方幫助文件將其描述為測量系統運行時間並優化進程的方法。將你真正想要改進的巨集部分封裝起來,而不是測量工作簿開啟時間、使用者提示時間或無關的設定時間。
Dim t0 As Long, elapsed As Long
t0 = GetSystemTicks()
' Run the work you want to measure here.
elapsed = GetSystemTicks() - t0
MsgBox "Elapsed ticks: " & elapsed
對同一文件副本多次執行相同的操作。第一次運行的結果可能會因檔案系統快取、公式狀態或其他一次性操作而有所不同。請記錄資料集大小、處理範圍以及是否啟用了自動計算,以確保比較結果的有效性。
好的結果不僅僅是運行時間更短。也要確認行數、總計、公式、文字值、日期以及所有輸出範圍是否仍與基準值一致。
官方參考:LibreOffice 幫助:GetSystemTicks 函數。
如果巨集循環遍歷一大片區域並反覆呼叫諸如 `move()` 之類的方法getCellByPosition(),那麼這種模式通常是首先要檢查的地方。 UNO API 公開了 `move()`XCellRangeData.getDataArray()和`move_range()` 方法,setDataArray()專門用於將整個單元格區域作為陣列移動。
官方 API 說明中指出,函數getDataArray()傳回一個行序列,每行包含若干列。傳回值可以是字串或雙精度浮點數。此函數setDataArray()會將一個陣列寫回指定範圍,且陣列的維度必須與該範圍相符。
例如,假設 A 列到 E 列包含巨集要轉換的輸入資料。與其逐一讀取每個單元格,不如一次選擇整個範圍:
Dim doc As Object
Dim sheet As Object
Dim sourceRange As Object
Dim data As Variant
doc = ThisComponent
sheet = doc.Sheets.getByName("Data")
' Example only: A2:E50001.
sourceRange = sheet.getCellRangeByPosition(0, 1, 4, 50000)
data = sourceRange.getDataArray()
在基本記憶體中進行處理data,然後將結果陣列一次寫入匹配的目標區域。與數千次單獨的讀寫操作相比,這大大減少了 UNO 呼叫次數。
官方參考資料:LibreOffice SDK:XCellRangeData和LibreOffice SDK:XCellRange。
批次存取數組固然有用,但將過大的工作表轉換為陣列只會將瓶頸轉移到記憶體。如果任務僅涉及特定表格,請避免硬編碼整列或整個 Calc 網格。
利用工作簿中已知的資訊(例如匯入行數、資料庫結果大小、指定的鍵列或應用程式建立的範圍)來確定最後一個有效行。然後僅請求巨集所需的行和列。
當工作表中包含大量格式信息,而實際數據卻被格式信息淹沒,或者舊內容佔用了大量內存空間時,這一點尤其重要。大型記憶體數組會消耗大量 RAM,一次過大的記憶體分配可能比處理適中的記憶體區塊更糟。
如果單一陣列導致記憶體使用量急遽上升、處理開始前出現長時間停頓,或接近機器的實際處理極限,則應分塊處理資料。例如,先處理幾千行數據,寫入結果,然後再處理下一個資料區塊。沒有通用的理想資料區塊大小;請使用實際的工作簿和硬體進行測試。
Calc 文件實作了 LibreOffice 的XModel介面。它的lockControllers()方法會暫停一些用於顯示更新的控制器通知,並在unlockControllers()巨集執行大量變更時恢復這些通知。這可以減少不必要的視覺操作。
Dim doc As Object
doc = ThisComponent
doc.lockControllers()
' Perform bulk changes here.
doc.unlockControllers()
官方 API 明確指出,控制器鎖定和解鎖操作必須成對進行。這意味著生產環境中的巨集應該包含錯誤處理機制,unlockControllers()即使處理失敗也能確保執行到位。文件保持鎖定狀態並非效能最佳化,而是清理路徑有缺陷。
官方參考:LibreOffice SDK:XModel。
如果巨集重複更改多個公式所依賴的儲存格,Calc 可能會花費大量時間重新計算,而巨集仍在更新中間值。電子表格文件公開了接口,XCalculatable包括isAutomaticCalculationEnabled()、、和。enableAutomaticCalculation()calculate()calculateAll()
更安全的做法是記住使用者目前的計算模式,僅在更新期間停用自動計算,更新後恢復原始狀態:
Dim doc As Object
Dim wasAutoCalc As Boolean
doc = ThisComponent
wasAutoCalc = doc.isAutomaticCalculationEnabled()
doc.enableAutomaticCalculation(False)
' Perform bulk updates.
doc.enableAutomaticCalculation(wasAutoCalc)
If wasAutoCalc Then
doc.calculate()
End If
calculate()重新計算髒單元格。calculateAll()它會重新計算每個單元格,這本身可能很耗費資源,因此不要僅僅因為巨集運行完畢就自動調用它。僅當工作簿邏輯確實需要時才使用完全重新計算。
與控制器鎖定類似,應在錯誤清理路徑中恢復計算狀態。巨集不應在靜默的情況下將使用者的工作簿保持在手動計算模式。
官方參考:LibreOffice SDK:XCalculatable。
最有效的結構通常是:確定一個精確的範圍,讀取一次,在記憶體中處理值,批量寫入結果,並且僅在該操作期間抑制不必要的 UI 或重新計算工作。
LibreOffice Basic 中一個實用的清理模式如下所示:
Sub ProcessLargeData
Dim doc As Object
Dim sheet As Object
Dim dataRange As Object
Dim data As Variant
Dim wasAutoCalc As Boolean
On Error GoTo CleanUp
doc = ThisComponent
sheet = doc.Sheets.getByName("Data")
dataRange = sheet.getCellRangeByPosition(0, 1, 4, 50000)
wasAutoCalc = doc.isAutomaticCalculationEnabled()
doc.lockControllers()
doc.enableAutomaticCalculation(False)
data = dataRange.getDataArray()
' Transform data in memory here.
' Build an output array with dimensions matching its target range.
CleanUp:
doc.enableAutomaticCalculation(wasAutoCalc)
If doc.hasControllersLocked() Then
doc.unlockControllers()
End If
If wasAutoCalc Then
doc.calculate()
End If
End Sub
範例中故意省略了轉換邏輯,因為這部分取決於您的工作簿。重要的最佳化在於工作流程的結構,而不是人為設定的業務計算。
LibreOffice Basic 可以透過此服務呼叫 Calc 函數com.sun.star.sheet.FunctionAccess。如果您的巨集手動實現了 Calc 已提供的查找、聚合或其他操作,使用內建函數可以簡化程式碼並減少自訂循環。
這並不能保證每個內建函數都優於每個自訂演算法。請對實際工作負載進行基準測試。官方說明文件展示如何從 Basic 呼叫 Calc 函數,並指出函數名稱以英文提供。
官方參考:LibreOffice 幫助:在巨集中使用 Calc 函數。
| 查看 | 好兆頭 | 何時改變策略 |
|---|---|---|
| 運行時 | 重複跑動距離始終短於基線距離。 | 大部分時間仍然花費在一個部分;請單獨分析該部分。 |
| 正確性 | 總計、行數、公式和代表性記錄與原始巨集相符。 | 數組轉換會改變資料類型或輸出維度。 |
| 記憶 | 大批量採購可以輕鬆滿足需求,無需換貨或長時間的分配暫停。 | 當全範圍數組過大時,請使用較小的資料塊。 |
| 重新計算 | 公式計算在主更新之後執行一次,而不是每次寫入之後都執行。 | 公式依賴關係需要中間計算值。 |
| 使用者介面行為 | 文件在計算完成或失敗後恢復正常顯示和計算狀態。 | 如果狀態可能被改變,則需要增加更強大的清理/錯誤處理機制。 |
getDataArray()仍然逐個單元格寫回每個結果。calculateAll()即使只有髒單元格需要重新計算,也在每個小批次處理後呼叫。陣列傳輸主要降低電子表格物件的存取開銷,但並不能解決演算法本身固有的開銷問題。例如,即使所有值都已載入到記憶體中,對每一行進行嵌套比較仍然可能很慢。在這種情況下,需要改進演算法:使用字典或索引,只排序一次而不是重複排序,減少重複操作,或者在電子表格不再適合執行的情況下,將工作負載遷移到更合適的資料處理工具。
這同樣適用於以網路呼叫、資料庫查詢、檔案 I/O 或外部服務為主的巨集。首先要進行測量,以便優化實際的瓶頸,而不是只優化可見的電子表格循環。
對於大型 Calc 資料集,減少 Basic 物件和電子表格物件之間的呼叫次數通常是最重要的結構性改進。每一次額外的最佳化應視為需要衡量的指標,而不是例行公事。只有當巨集運行速度更快且仍然正確、可預測且易於維護時,它才真正有用。
學習如何在 Word 中拖曳圖片、選擇文字環繞方式、將圖片與段落保持在一起或將其固定在頁面上,以及如何解決圖片無法移動的問題。
學習如何使用儲存格內工具在 Excel 中插入複選框,使用公式計算選取項目的數量,或在舊版桌面 Excel 中新增連結的表單控制項。
使用填充柄公式、SEQUENCE 或可重複使用的自訂清單在 Excel 中產生 A 到 Z、小寫字母或 Z 以上的標籤。
學習如何在 Windows、Mac 和網頁版 Excel 中新增刪除線、設定儲存格部分格式以及刪除線條而不刪除其值。
Microsoft Access 是一款 Windows 資料庫應用程序,用於儲存相關記錄、建立查詢、建立資料輸入表單和產生報表。了解它的工作原理以及適用場景。
了解如何在 Word 2010 中調整網格線高度和寬度、變更可見線頻率以及設定底層水平和垂直繪圖網格間距。
了解如何將 PST 檔案匯入 Outlook 2010 或匯出郵件、聯絡人、行事曆和任務。按照正確的選單操作,避免遺漏資料夾或重複文件。
使用 Kernel 的目前步驟還原忘記的 Outlook PST 密碼,包括如何識別正確的檔案、進行備份以及檢查工具的限制。
使用 LiveWeb 外掛程式將網站放置在 PowerPoint 投影片上,設定其大小和刷新行為,並在簡報前檢查相容性。
在 Word 2010 中設定預設字體、字號和文字效果,將選擇儲存到 Normal.dotm,然後修改 Normal 樣式以用於以後的文件。