My project involves parsing a word document to extract a set of tokens then allowing the user to selectively perform bulk actions on those tokens. Because of the UI step, I need to be able to call myRange.select()
and myRange.font.set(...)
on a subsequent Word.run(ctx => {...})
call from run which extracted the tokens.
If this is more appropriate as a stackoverflow post, I apologize and will repost there but it appears that the library is not matching the API, as I understand it. I could definitely be mistaken though.
Expected Behavior
I expect that calling Word.run(ctx => myRange.select())
would cause that range to be selected as that range was added to context.trackedObjects
on a previous run.
Current Behavior
Nothing happens, not even an error to the console.
note that the commented code of keeping the context
object on the Chunk
class and using that for subsequent runs will work on Word Online / Chrome but does not work in Windows or OSX Word
Your Environment
- Platform [PC desktop, Mac, iOS, Office Online]: Win11 desktop, OSX, Word Online (all most recent)
- Host [Excel, Word, PowerPoint, etc.]: Word
- Office version number: most recent
- Operating System: OSX / Win11
- Browser (if using Office Online): Chrome
Code:
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>
)
};
};
Version that works on WordOnline but not Windows or OSX:
(duplicate code from above elided)
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>
)
};
};