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:
|
def _open_document(self, doc_url: str, *, fast: bool = False) -> bool:
|
||||||
try:
|
try:
|
||||||
self._doc_url = doc_url
|
self._doc_url = doc_url
|
||||||
|
self._ensure_clipboard_permissions(doc_url)
|
||||||
if fast:
|
if fast:
|
||||||
doc_pages = self._find_doc_pages(doc_url)
|
doc_pages = self._find_doc_pages(doc_url)
|
||||||
if doc_pages:
|
if doc_pages:
|
||||||
@@ -232,6 +233,18 @@ class KDocsUploader:
|
|||||||
self._last_error = f"打开文档失败: {e}"
|
self._last_error = f"打开文档失败: {e}"
|
||||||
return False
|
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:
|
def _normalize_doc_url(self, url: str) -> str:
|
||||||
if not url:
|
if not url:
|
||||||
return ""
|
return ""
|
||||||
@@ -953,38 +966,70 @@ class KDocsUploader:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
def _get_current_cell_address(self) -> str:
|
def _get_current_cell_address(self) -> str:
|
||||||
name_box = self._page.locator('#root input[type="text"]').first
|
try:
|
||||||
return name_box.input_value()
|
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:
|
def _navigate_to_cell(self, cell_address: str) -> None:
|
||||||
name_box = self._page.locator('#root input[type="text"]').first
|
try:
|
||||||
name_box.click()
|
name_box = self._page.locator("input.edit-box").first
|
||||||
name_box.fill(cell_address)
|
name_box.click()
|
||||||
name_box.press("Enter")
|
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)
|
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:
|
def _get_cell_value(self, cell_address: str) -> str:
|
||||||
self._navigate_to_cell(cell_address)
|
self._navigate_to_cell(cell_address)
|
||||||
time.sleep(0.3)
|
time.sleep(0.3)
|
||||||
try:
|
try:
|
||||||
formula_bar = self._page.locator('input[type="text"]').nth(1)
|
self._page.evaluate("() => navigator.clipboard.writeText('')")
|
||||||
value = formula_bar.input_value()
|
|
||||||
if value:
|
|
||||||
return value.strip()
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
self._focus_grid()
|
||||||
try:
|
try:
|
||||||
formula_inputs = self._page.locator('textbox')
|
self._page.keyboard.press("Control+c")
|
||||||
for i in range(formula_inputs.count()):
|
time.sleep(0.2)
|
||||||
try:
|
value = self._read_clipboard_text()
|
||||||
value = formula_inputs.nth(i).input_value()
|
if value:
|
||||||
if value:
|
return value.strip()
|
||||||
import re
|
|
||||||
|
|
||||||
if not re.match(r"^[A-Z]+\d+$", value.strip()):
|
|
||||||
return value.strip()
|
|
||||||
except Exception:
|
|
||||||
continue
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return ""
|
return ""
|
||||||
@@ -1020,6 +1065,7 @@ class KDocsUploader:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def _search_person(self, name: str) -> None:
|
def _search_person(self, name: str) -> None:
|
||||||
|
self._focus_grid()
|
||||||
self._page.keyboard.press("Control+f")
|
self._page.keyboard.press("Control+f")
|
||||||
time.sleep(0.3)
|
time.sleep(0.3)
|
||||||
search_input = None
|
search_input = None
|
||||||
|
|||||||
Reference in New Issue
Block a user