Read KDocs cells via clipboard
This commit is contained in:
@@ -202,6 +202,7 @@ class KDocsUploader:
|
||||
def _open_document(self, doc_url: str, *, fast: bool = False) -> bool:
|
||||
try:
|
||||
self._doc_url = doc_url
|
||||
self._ensure_clipboard_permissions(doc_url)
|
||||
if fast:
|
||||
doc_pages = self._find_doc_pages(doc_url)
|
||||
if doc_pages:
|
||||
@@ -232,6 +233,18 @@ class KDocsUploader:
|
||||
self._last_error = f"打开文档失败: {e}"
|
||||
return False
|
||||
|
||||
def _ensure_clipboard_permissions(self, doc_url: str) -> None:
|
||||
if not self._context or not doc_url:
|
||||
return
|
||||
try:
|
||||
parsed = urlparse(doc_url)
|
||||
if not parsed.scheme or not parsed.netloc:
|
||||
return
|
||||
origin = f"{parsed.scheme}://{parsed.netloc}"
|
||||
self._context.grant_permissions(["clipboard-read", "clipboard-write"], origin=origin)
|
||||
except Exception:
|
||||
return
|
||||
|
||||
def _normalize_doc_url(self, url: str) -> str:
|
||||
if not url:
|
||||
return ""
|
||||
@@ -953,38 +966,70 @@ class KDocsUploader:
|
||||
continue
|
||||
|
||||
def _get_current_cell_address(self) -> str:
|
||||
try:
|
||||
name_box = self._page.locator("input.edit-box").first
|
||||
return name_box.input_value()
|
||||
except Exception:
|
||||
name_box = self._page.locator('#root input[type="text"]').first
|
||||
return name_box.input_value()
|
||||
|
||||
def _navigate_to_cell(self, cell_address: str) -> None:
|
||||
try:
|
||||
name_box = self._page.locator("input.edit-box").first
|
||||
name_box.click()
|
||||
name_box.fill(cell_address)
|
||||
name_box.press("Enter")
|
||||
except Exception:
|
||||
name_box = self._page.locator('#root input[type="text"]').first
|
||||
name_box.click()
|
||||
name_box.fill(cell_address)
|
||||
name_box.press("Enter")
|
||||
time.sleep(0.3)
|
||||
|
||||
def _focus_grid(self) -> None:
|
||||
try:
|
||||
info = self._page.evaluate(
|
||||
"""() => {
|
||||
const canvases = Array.from(document.querySelectorAll("canvas"));
|
||||
let best = null;
|
||||
for (const c of canvases) {
|
||||
const rect = c.getBoundingClientRect();
|
||||
if (!rect.width || !rect.height) continue;
|
||||
if (rect.width < 200 || rect.height < 200) continue;
|
||||
const area = rect.width * rect.height;
|
||||
if (!best || area > best.area) {
|
||||
best = {x: rect.left + rect.width / 2, y: rect.top + rect.height / 2, area};
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}"""
|
||||
)
|
||||
if info and info.get("x") and info.get("y"):
|
||||
self._page.mouse.click(info["x"], info["y"])
|
||||
time.sleep(0.1)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _read_clipboard_text(self) -> str:
|
||||
try:
|
||||
return self._page.evaluate("() => navigator.clipboard.readText()") or ""
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
def _get_cell_value(self, cell_address: str) -> str:
|
||||
self._navigate_to_cell(cell_address)
|
||||
time.sleep(0.3)
|
||||
try:
|
||||
formula_bar = self._page.locator('input[type="text"]').nth(1)
|
||||
value = formula_bar.input_value()
|
||||
if value:
|
||||
return value.strip()
|
||||
self._page.evaluate("() => navigator.clipboard.writeText('')")
|
||||
except Exception:
|
||||
pass
|
||||
self._focus_grid()
|
||||
try:
|
||||
formula_inputs = self._page.locator('textbox')
|
||||
for i in range(formula_inputs.count()):
|
||||
try:
|
||||
value = formula_inputs.nth(i).input_value()
|
||||
self._page.keyboard.press("Control+c")
|
||||
time.sleep(0.2)
|
||||
value = self._read_clipboard_text()
|
||||
if value:
|
||||
import re
|
||||
|
||||
if not re.match(r"^[A-Z]+\d+$", value.strip()):
|
||||
return value.strip()
|
||||
except Exception:
|
||||
continue
|
||||
except Exception:
|
||||
pass
|
||||
return ""
|
||||
@@ -1020,6 +1065,7 @@ class KDocsUploader:
|
||||
return True
|
||||
|
||||
def _search_person(self, name: str) -> None:
|
||||
self._focus_grid()
|
||||
self._page.keyboard.press("Control+f")
|
||||
time.sleep(0.3)
|
||||
search_input = None
|
||||
|
||||
Reference in New Issue
Block a user