insertFileFromBase64 causes accumulation of styles

Hanna Lebedenko 20 Reputation points
2024-05-02T09:31:53.63+00:00

We're working on an add-in for Word that involves opening multiple documents.

However, we've encountered an issue: when we use context.document.insertFileFromBase64 to open several documents, the styles from these base64 documents are being "merged" in the "Styles Gallery". In other words, if there were no both custom and built-in styles in the "Styles Gallery" when the add-in was initially launched, opening subsequent documents results in the accumulation of styles, leading to potentially hundreds of redundant styles cluttering Styles Gallery.

What we expect is that when a document is opened using context.document.insertFileFromBase64, only the styles specific to that particular document should be applied. It seems that the JavaScript API doesn't support this behavior.

To address this, our current workaround idea involves deleting custom styles and hiding built-in ones just before using context.document.insertFileFromBase64.
Something like that:

export const insertDocument = async (
  fileDataBase64: string,
  document: DocumentAndStyles, //global state of initial document and styles
) => {
  return Word.run(async (context) => {
    let currentStyles = context.document.getStyles();
    currentStyles.load({ builtIn: true });

    await context.sync().then(() => {
      //delete all styles
      currentStyles.items.forEach((style) => {
        if (!style.builtIn) {
          style.delete();
        }
      });
      //set initial document
      context.document.set(document.document as Word.Document);
      //set initial styles
      context.document.importStylesFromJson(JSON.stringify(document.styles));
      //insert new file, import new styles
      context.document.insertFileFromBase64(fileDataBase64, "Replace", {
        importTheme: true,
        importStyles: true,
        importParagraphSpacing: true,
        importPageColor: true,
        importChangeTrackingMode: false,
      });

      return context.sync();
    });
  });
};

This approach has poor performance and after several switches through documents the error occurs.

Are there any alternative solutions or workarounds?

Word
Word
A family of Microsoft word processing software products for creating web, email, and print documents.
878 questions
JavaScript API
JavaScript API
An Office service that supports add-ins to interact with objects in Office client applications.
995 questions
Office Development
Office Development
Office: A suite of Microsoft productivity software that supports common business tasks, including word processing, email, presentations, and data management and analysis.Development: The process of researching, productizing, and refining new or existing technologies.
3,971 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Stephen Baker 80 Reputation points
    2024-05-16T11:41:40.5766667+00:00

    The issue you’re experiencing with context.document.insertFileFromBase64 merging styles from multiple documents into the Styles Gallery is indeed a known problem. The JavaScript API for Office (Office.js) currently does not provide a built-in method to isolate styles when inserting documents using insertFileFromBase64. Your approach to delete custom styles and hide built-in ones before inserting a new document is a common workaround. Save the initial styles and document state in a global variable during Office.initialize or Office.onReady. Before inserting a new document, clear the current styles and apply the initial saved styles. Medical Insurance California

    Office.onReady((info) => {

    // Save the initial styles and document state

    let initialState = {

    styles: null,
    
    document: null
    ```  };
    
      Word.run((context) => {
    
    ```java
    // Load the current styles and document
    
    let currentStyles = context.document.getStyles();
    
    currentStyles.load();
    
    let currentDocument = context.document;
    
    currentDocument.load();
    
    return context.sync().then(() => {
    
      // Save the initial state
    
      initialState.styles = currentStyles.items;
    
      initialState.document = currentDocument;
    
    });
    ```  });
    
    });
    
    export const insertDocument = async (fileDataBase64) => {
    
      return Word.run(async (context) => {
    
    ```typescript
    // Clear current styles and apply initial styles
    
    let currentStyles = context.document.getStyles();
    
    currentStyles.load({ builtIn: true });
    
    await context.sync().then(() => {
    
      currentStyles.items.forEach((style) => {
    
        if (!style.builtIn) {
    
          style.delete();
    
        }
    
      });
    
      // Apply initial styles (assuming initialState is accessible)
    
      context.document.importStylesFromJson(JSON.stringify(initialState.styles));
    
    });
    
    // Insert new file
    
    context.document.insertFileFromBase64(fileDataBase64, "Replace", {
    
      importTheme: true,
    
      importStyles: true,
    
      importParagraphSpacing: true,
    
      importPageColor: true,
    
      importChangeTrackingMode: false,
    
    });
    
    return context.sync();
    ```  });
    
    };
    
    

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.