本文介绍了似乎不能跨Office JS中对Word.run(Context=>{...})的调用使用范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的项目涉及解析Word文档以提取一组令牌,然后允许用户有选择地对这些令牌执行批量操作。由于UI步骤,我需要能够从提取令牌的Run调用后续myRange.select()myRange.font.set(...)

如果这更适合作为堆栈溢出帖子,我很抱歉,并将在那里重新发布,但据我所知,库似乎与API不匹配。不过,我肯定会弄错的。

预期行为

我希望调用Word.run(ctx => myRange.select())会导致选择该范围,因为该范围是在上一次运行时添加到context.trackedObjects的。

当前行为

没有任何反应,甚至控制台也没有错误。

注意context对象保留在Chunk类上并将其用于后续运行的注释代码将在Word Online/Chrome上运行,但不能在Windows或OSX Word中运行

您的环境

  • 平台[PC台式机、Mac、iOS、Office Online]:Win11台式机、OSX、Word Online(均为最新版本)
  • 主机[Excel、Word、PowerPoint等]:Word
  • Office版本号:最新
  • 操作系统:OSX/Win11
  • 浏览器(如果使用Office Online):Chrome

代码:

import * as React from 'react'
import { Container, ListGroup, ListGroupItem, Button, Label, Input, ButtonGroup, Row } from 'reactstrap'

class Chunk {
    range: Word.Range
    text: string
    // context: Word.RequestContext
    constructor(t: string, r: Word.Range, ctx: Word.RequestContext) {
        this.range = r
        this.text = t
        ctx.trackedObjects.add(r)
        r.track()
        // this.context = ctx
    }
    async select(ctx: Word.RequestContext) {
        console.log('select')
        this.range.select('Select')
        ctx.sync()
    }
}

const getChunks = async () => {
    return Word.run(async context => {
        let paragraphs = context.document.body.paragraphs.load()
        let wordRanges: Array<Word.RangeCollection> = []
        await context.sync()
        paragraphs.items.forEach(paragraph => {
            const ranges = paragraph.getTextRanges([' ', ',', '.', ']', ')'], true)
            ranges.load('text')
            wordRanges.push(ranges)
        })
        await context.sync()
        let chunks: Chunk[] = []
        wordRanges.forEach(ranges => ranges.items.forEach(range => {
            chunks.push(new Chunk(range.text, range, context))
        }))
        await context.sync()
        return chunks
    })

}

interface ChunkControlProps { chunk: Chunk; onSelect: (e: React.MouseEvent<HTMLElement>) => void }
export const ChunkControl: React.SFC<ChunkControlProps> = ({ chunk, onSelect}) => {
    return (
        <div style={{marginLeft: '0.5em'}}><a href='#' onClick={onSelect}>{chunk.text}</a></div>
    )
}
export class App extends React.Component<{title: string}, {chunks: Chunk[]}> {
    constructor(props, context) {
        super(props, context)
        this.state = { chunks: [] }
    }

    componentDidMount() { this.click() }

    click = async () => {
        const chunks = await getChunks()
        this.setState(prev => ({ ...prev, chunks: chunks }))
    }

    onSelectRange(chunk: Chunk) {
        return async (e: React.MouseEvent<HTMLElement>) => {
            e.preventDefault()
            Word.run(ctx => chunk.select(ctx))
        }
    }

    render() {
        return (
            <Container fluid={true}>
                <Button color='primary' size='sm' block className='ms-welcome__action' onClick={this.click}>Find Chunks</Button>
                <hr/>
                <ListGroup>
                    {this.state.chunks.map((chunk, idx) => (
                        <ListGroupItem key={idx}>
                            <ChunkControl  onSelect={this.onSelectRange(chunk)} chunk={chunk}/>
                        </ListGroupItem>
                    ))}
                </ListGroup>
            </Container>
        )
    };
};

可在WordOnline上运行但不能在Windows或OSX上运行的版本:

(来自上面省略的重复代码)

 class Chunk {
    range: Word.Range
    text: string
    context: Word.RequestContext
    constructor(t: string, r: Word.Range, ctx: Word.RequestContext) {
        this.range = r
        this.text = t
        this.context = ctx
    }
    async select() {
        this.range.select('Select')
        ctx.sync()
    }
}

const getChunks = async () => {
    return Word.run(async context => {
        ...
    })

}

...

export class App extends React.Component<{title: string}, {chunks: Chunk[]}> {
    constructor(props, context) {
        super(props, context)
        this.state = { chunks: [] }
    }

    componentDidMount() { this.click() }

    click = async () => {
        const chunks = await getChunks()
        this.setState(prev => ({ ...prev, chunks: chunks }))
    }

    onSelectRange(chunk: Chunk) {
        return async (e: React.MouseEvent<HTMLElement>) => {
            e.preventDefault()
            chunk.select()
        }
    }

    render() {
        return (
            <Container fluid={true}>
                <Button color='primary' size='sm' block className='ms-welcome__action' onClick={this.click}>Find Chunks</Button>
                <hr/>
                <ListGroup>
                    {this.state.chunks.map((chunk, idx) => (
                        <ListGroupItem key={idx}>
                            <ChunkControl  onSelect={this.onSelectRange(chunk)} chunk={chunk}/>
                        </ListGroupItem>
                    ))}
                </ListGroup>
            </Container>
        )
    };
};

推荐答案

就一般模式而言:诀窍是像通常那样执行Word.run,而不是让它创建一个新的匿名请求上下文,使用某个现有对象的上下文恢复运行。要继续使用现有上下文,只需使用以下函数之一可从Word.run获得的重载;即,接受对象(或对象数组)作为第一个参数,批处理作为第二个参数:

请注意,为了能够跨不同的range.track()以延长其生存期;并且您应该在某个时候使用range.untrack()将其清除。

上面的文本和代码样例来自我的书Building Office Add-ins using Office.js。那里还有更多的信息。特别是在一个部分中粘贴:

本书中可能对您有帮助的相关章节:

至于您对在线和Windows/Mac之间的行为差异的观察--这非常有趣,听起来像是一个应该调查的错误。你介意在https://github.com/OfficeDev/office-js/issues上只为那个特定的方面提交一个错误,并尽可能少地重现吗?(很抱歉让您来回走动,我知道您在https://github.com/OfficeDev/office-js/issues/68已经在那里了;但我想区分一下概念问题,它实际上只是一个问题(和文档问题),与从行为差异中看到的可能的错误)。

最佳!

~Michael

这篇关于似乎不能跨Office JS中对Word.run(Context=&gt;{...})的调用使用范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 08:28