在Office JS中调用Word.run(context => {...})时,似乎无法使用范围

时间:2018-02-21 17:54:30

标签: typescript office-js

我的项目涉及解析word文档以提取一组标记,然后允许用户有选择地对这些标记执行批量操作。由于用户界面步骤,我需要能够在后续myRange.select()来自运行的myRange.font.set(...)调用中调用Word.run(ctx => {...})Word.run(ctx => myRange.select())

如果这更适合作为stackoverflow帖子,我道歉并将在那里重新发布,但看起来该库与API不匹配,正如我所理解的那样。我当然肯定会弄错。

预期行为

我希望调用context.trackedObjects会导致选择该范围,因为该范围在之前的运行中已添加到context

当前行为

没有任何事情发生,甚至连控制台都没有错误。

note Chunk类保留在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> ) }; }; 类并将其用于后续运行的注释代码可以在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

代码:

 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>
        )
    };
};

适用于WordOnline但不适用于Windows或OSX的版本:

(上述重复代码已删除)

User.left_outer_joins(:houses, :cars)
    .select("users.id, count(houses.id), count(cars.id)")
    .group("users.id")
    .having("count(houses.id) > 0 OR count(cars.id) > 0")

1 个答案:

答案 0 :(得分:2)

就一般模式而言:诀窍是像往常一样做Word.run,而不是让它创建一个新的匿名请求 上下文,使用某些现有对象的上下文运行恢复。 要继续使用现有上下文,只需使用其中一个函数即可 Word.run提供的重载;即,一个过载,一个 对象(或对象数组)作为第一个参数,批处理作为第二个参数:

Code sample

请注意,为了能够在不同的run - s中使用Range对象,您需要在第一次运行完成之前调用range.track()以延长其生命周期;你应该使用range.untrack()在某个时候清理它。

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

What happens when you forget to pass in a Range object

本书的相关章节您可能会觉得有用:

TOC

至于您对Online和Windows / Mac之间行为差异的观察 - 这非常有趣,听起来像是应该调查的错误。您是否介意在https://github.com/OfficeDev/office-js/issues处以最小的复制品为该特定方面提交错误? (抱歉让你来回发送,我知道你已经去过https://github.com/OfficeDev/office-js/issues/68;但是我想把概念问题分开,这个问题实际上只是一个问题(和文档问题),而不是像从行为的差异看。)

最佳!

〜迈克尔