使用Office.js开发Office Web Add-in:多任务窗格事件共享及PDF联动问询
Hey there! Let's walk through solving your specific scenario where selecting content in one task pane triggers a PDF display in another, plus cover general methods for sharing events across multiple Office.js task panes.
Part 1: Step-by-Step for Your PDF Display Scenario
We'll use Office.js's built-in storage system to share state between panes, since it's tightly integrated with the Office ecosystem and handles cross-iframe communication seamlessly.
1. Capture Selection & Store Data in the First Task Pane
First, in the task pane where users select content, we'll listen for selection changes, grab the selected text, and store the relevant PDF metadata (like its URL) in Office's shared storage.
Office.onReady(async () => { // Listen for Word's selection change event await Office.context.document.addHandlerAsync( Office.EventType.DocumentSelectionChanged, async () => { // Fetch the selected text from Word const selectedText = await Word.run(async (context) => { const selectionRange = context.document.getSelection(); selectionRange.load('text'); await context.sync(); return selectionRange.text; }); // Replace this with your logic to map selected text to a PDF URL const targetPdfUrl = `https://your-addin-domain.com/pdfs/${selectedText.replace(/\s+/g, '-')}.pdf`; // Store the selection + PDF data in shared storage await Office.runtime.storage.setItemAsync('selectedContent', JSON.stringify({ selectedText, pdfUrl: targetPdfUrl })); } ); });
2. Listen for Updates & Display PDF in the Second Task Pane
In your PDF-displaying task pane, we'll watch for changes to the shared storage. When the selectedContent key updates, we'll pull the PDF URL and render it in the pane.
Office.onReady(async () => { // Get reference to your PDF container element const pdfContainer = document.getElementById('pdf-container'); // Listen for changes to the shared storage await Office.runtime.storage.addHandlerAsync( Office.EventType.StorageChanged, async (eventArgs) => { if (eventArgs.key === 'selectedContent') { const { pdfUrl } = JSON.parse(eventArgs.newValue); // Render the PDF using an embed tag (adjust dimensions as needed) pdfContainer.innerHTML = `<embed src="${pdfUrl}" type="application/pdf" width="100%" height="600px" />`; } } ); // Initialize with existing data (in case a selection was made before this pane opened) const initialStorageData = await Office.runtime.storage.getItemAsync('selectedContent'); if (initialStorageData.value) { const { pdfUrl } = JSON.parse(initialStorageData.value); pdfContainer.innerHTML = `<embed src="${pdfUrl}" type="application/pdf" width="100%" height="600px" />`; } });
Part 2: General Methods for Cross-Taskpane Event Sharing
Beyond the storage approach, here are two other reliable methods for sharing events between Office.js task panes:
1. Office.js Message Passing (For Dialog-Style Panes)
If your second task pane is opened as a dialog via displayDialogAsync, use Office's built-in message passing system for real-time bidirectional communication:
In the Main Task Pane (Opening the Dialog)
let pdfDialog; // Open the PDF task pane as a dialog Office.context.ui.displayDialogAsync('https://your-addin-domain.com/pdf-pane.html', { height: 85, width: 70, displayInIframe: true }, (result) => { pdfDialog = result.value; // Listen for messages from the dialog pdfDialog.addEventHandler(Office.EventType.DialogMessageReceived, (args) => { console.log('Dialog sent:', args.message); }); }); // Send selection data to the dialog when a selection changes async function sendSelectionToDialog(selectedText) { const targetPdfUrl = `https://your-addin-domain.com/pdfs/${selectedText.replace(/\s+/g, '-')}.pdf`; pdfDialog.postMessage(JSON.stringify({ pdfUrl: targetPdfUrl })); }
In the Dialog (PDF Task Pane)
Office.onReady(async () => { const pdfContainer = document.getElementById('pdf-container'); // Listen for messages from the main task pane Office.context.ui.addHandlerAsync(Office.EventType.DialogMessageReceived, (args) => { const { pdfUrl } = JSON.parse(args.message); pdfContainer.innerHTML = `<embed src="${pdfUrl}" type="application/pdf" width="100%" height="600px" />`; }); // Send a confirmation back to the main pane (optional) Office.context.ui.messageParent('PDF pane is ready!'); });
2. Browser Broadcast Channel API (Native & Flexible)
Since all task panes run under your add-in's domain, you can use the browser's native Broadcast Channel API to broadcast events across iframes. It's lightweight and doesn't depend on Office.js specifics:
In the Selection Task Pane
// Create a shared channel (use the same name across all panes) const addinChannel = new BroadcastChannel('office-addin-shared-channel'); // Broadcast selection data when a selection changes async function broadcastSelection() { const selectedText = await Word.run(async (context) => { const range = context.document.getSelection(); range.load('text'); await context.sync(); return range.text; }); const targetPdfUrl = `https://your-addin-domain.com/pdfs/${selectedText.replace(/\s+/g, '-')}.pdf`; addinChannel.postMessage({ eventType: 'contentSelected', payload: { pdfUrl: targetPdfUrl } }); } // Hook into the selection change event Office.context.document.addHandlerAsync(Office.EventType.DocumentSelectionChanged, broadcastSelection);
In the PDF Task Pane
const addinChannel = new BroadcastChannel('office-addin-shared-channel'); const pdfContainer = document.getElementById('pdf-container'); // Listen for broadcasted events addinChannel.onmessage = (event) => { if (event.data.eventType === 'contentSelected') { const { pdfUrl } = event.data.payload; pdfContainer.innerHTML = `<embed src="${pdfUrl}" type="application/pdf" width="100%" height="600px" />`; } };
Quick Comparison of Methods
| Method | Best For | Pros | Cons |
|---|---|---|---|
Office.runtime.storage | Persisting state between panes | Deep Office integration, auto-sync | Limited to key-value storage |
| Office.js Message Passing | Dialog-style pane communication | Official Office-supported, bidirectional | Tied to dialog lifecycle |
| Broadcast Channel API | Simple event broadcasting | Native browser API, flexible, fast | Requires modern browser support (all major browsers support it now) |
内容的提问来源于stack exchange,提问作者Rahul Bisht

