Configuring Fonts for Rendering Spreadsheets with JavaScript via C++
Possible Usage Scenarios
Aspose.Cells APIs provide the facility to render the spreadsheets in image formats as well as convert them to PDF & XPS formats. In order to maximize the conversion fidelity, it is necessary that the fonts used in the spreadsheet should be available in the operating system’s default font directory. In case the required fonts are not present, then the Aspose.Cells APIs will try to substitute the required fonts with the ones available.
Selection of Fonts
Below is the process that Aspose.Cells APIs follow behind the scene.
- The API tries to find the fonts on the file system matching the exact font name used in the spreadsheet.
- If API cannot find the fonts with the exact same name, it attempts to use the default font specified under the Workbook’s DefaultStyle.font property.
- If API cannot locate the font defined under the workbook’s DefaultStyle.font property, it attempts to use the font specified under PdfSaveOptions.defaultFont or ImageOrPrintOptions.defaultFont property.
- If API cannot locate the font defined under PdfSaveOptions.defaultFont or ImageOrPrintOptions.defaultFont property, it attempts to use the font specified under FontConfigs.defaultFontName property.
- If API cannot locate the font defined under FontConfigs.defaultFontName property, it attempts to select the most suitable fonts from all of the available fonts.
- Finally, if API cannot find any fonts on the file system, it renders the spreadsheet using Arial.
Set Custom Font Folders
Aspose.Cells APIs search the operating system’s default font directory for the required fonts. In case the required fonts are not available in the system’s font directory, then the APIs search through the custom (user-defined) directories. The FontConfigs class has exposed a number of ways to set custom font directories as detailed below.
- FontConfigs.fontFolder(string, boolean): This method is useful if there is only one folder to be set.
- **FontConfigs.fontFolders(string[], boolean)**: This method is useful when the fonts reside in multiple folders and the user wishes to set all folders separately rather than combining all fonts in a single folder.
- **FontConfigs.fontSources(FontSourceBase[])**: This mechanism is useful when the user wishes to load fonts from multiple folders or a single font file or font data from an array of bytes.
<!DOCTYPE html>
<html>
<head>
<title>Aspose.Cells Font Configuration Example</title>
</head>
<body>
<h1>Aspose.Cells Font Configuration Example</h1>
<p>Select an Excel file (optional) and font resources to configure Aspose.Cells font sources in the browser.</p>
<label>Excel File (optional):</label>
<input type="file" id="fileInput" accept=".xls,.xlsx,.csv" />
<br/><br/>
<label>Font File (.ttf/.otf) (optional):</label>
<input type="file" id="fontFileInput" accept=".ttf,.otf" />
<br/><br/>
<label>Font Folder (optional, select a folder):</label>
<input type="file" id="fontFolderInput" webkitdirectory directory multiple />
<br/><br/>
<button id="runExample">Configure Fonts</button>
<a id="downloadLink" style="display: none;">Download Result</a>
<div id="result"></div>
</body>
<script src="aspose.cells.js.min.js"></script>
<script type="text/javascript">
const { Workbook, SaveFormat, Utils } = AsposeCells;
AsposeCells.onReady({
license: "/lic/aspose.cells.enc",
fontPath: "/fonts/",
fontList: [
"arial.ttf",
"NotoSansSC-Regular.ttf"
]
}).then(() => {
console.log("Aspose.Cells initialized");
});
document.getElementById('runExample').addEventListener('click', async () => {
const fileInput = document.getElementById('fileInput');
const fontFileInput = document.getElementById('fontFileInput');
const fontFolderInput = document.getElementById('fontFolderInput');
const resultDiv = document.getElementById('result');
// Basic validation: ensure at least one font resource is provided (file or folder)
if (!fontFileInput.files.length && !fontFolderInput.files.length) {
resultDiv.innerHTML = '<p style="color: red;">Please select at least one font file or a font folder.</p>';
return;
}
// Defining string variables to store paths/names to font folders & font file
// (In browser environment we use simple names or uploaded file names)
const fontFolder1 = "Arial";
const fontFolder2 = "Calibri";
const fontFile = "arial.ttf";
// Setting first font folder (converted from setFontFolder)
AsposeCells.FontConfigs.fontFolder = fontFolder1;
// Preserve the subfolder-search flag from original API call as a separate property
AsposeCells.FontConfigs.fontFolderSearchSubFolders = true;
// Setting both font folders (converted from setFontFolders)
AsposeCells.FontConfigs.fontFolders = [fontFolder1, fontFolder2];
// Preserve the subfolder-search flag as a separate property
AsposeCells.FontConfigs.fontFoldersSearchSubFolders = false;
// Defining FolderFontSource
const sourceFolder = new AsposeCells.FolderFontSource(fontFolder1, false);
// Defining FileFontSource
const sourceFile = new AsposeCells.FileFontSource(fontFile);
// Defining MemoryFontSource
let memoryFontBytes = new Uint8Array([]);
if (fontFileInput.files.length) {
const ff = fontFileInput.files[0];
const arrayBuffer = await ff.arrayBuffer();
memoryFontBytes = new Uint8Array(arrayBuffer);
} else if (fontFolderInput.files.length) {
// If a folder was provided, try to find a .ttf/.otf inside it and use the first found
const files = Array.from(fontFolderInput.files);
const fontCandidate = files.find(f => f.name.toLowerCase().endsWith('.ttf') || f.name.toLowerCase().endsWith('.otf'));
if (fontCandidate) {
const arrayBuffer = await fontCandidate.arrayBuffer();
memoryFontBytes = new Uint8Array(arrayBuffer);
}
}
const sourceMemory = new AsposeCells.MemoryFontSource(memoryFontBytes);
// Setting font sources (converted from setFontSources)
AsposeCells.FontConfigs.fontSources = [sourceFolder, sourceFile, sourceMemory];
// Provide feedback to the user
resultDiv.innerHTML = '<p style="color: green;">Font configuration applied successfully.</p>';
});
</script>
</html>
Font Substitution Mechanism
Aspose.Cells APIs also provide the ability to specify the substitute font for rendering purposes. This mechanism is helpful when a required font is not available on the machine where conversion has to take place. Users can provide a list of font names as an alternative to the originally required font. In order to achieve this, the Aspose.Cells APIs have exposed the **FontConfigs.fontSubstitutes(string, string[])** method which accepts 2 parameters. The first parameter is of type string, which should be the name of the font that needs to be substituted. The second parameter is an array of type string. Users can provide a list of font names as a substitution for the original font name (specified in the first parameter).
Here is a simple usage scenario.
<!DOCTYPE html>
<html>
<head>
<title>Aspose.Cells Example</title>
</head>
<body>
<h1>Example Title</h1>
<input type="file" id="fileInput" accept=".xls,.xlsx,.csv" />
<button id="runExample">Run Example</button>
<a id="downloadLink" style="display: none;">Download Result</a>
<div id="result"></div>
</body>
<script src="aspose.cells.js.min.js"></script>
<script type="text/javascript">
const { Workbook, SaveFormat, Utils } = AsposeCells;
AsposeCells.onReady({
license: "/lic/aspose.cells.enc",
fontPath: "/fonts/",
fontList: [
"arial.ttf",
"NotoSansSC-Regular.ttf"
]
}).then(() => {
console.log("Aspose.Cells initialized");
});
document.getElementById('runExample').addEventListener('click', async () => {
const fileInput = document.getElementById('fileInput');
if (!fileInput.files.length) {
document.getElementById('result').innerHTML = '<p style="color: red;">Please select an Excel file.</p>';
return;
}
const file = fileInput.files[0];
const arrayBuffer = await file.arrayBuffer();
// Instantiating a Workbook object by opening the Excel file through the file stream
const workbook = new Workbook(new Uint8Array(arrayBuffer));
// Substituting the Arial font with Times New Roman & Calibri
// Converted from: AsposeCells.FontConfigs.setFontSubstitutes("Arial", ["Times New Roman", "Calibri"]);
AsposeCells.FontConfigs.fontSubstitutes = { "Arial": ["Times New Roman", "Calibri"] };
// Saving the (possibly modified) workbook
const outputData = workbook.save(SaveFormat.Xlsx);
const blob = new Blob([outputData]);
const downloadLink = document.getElementById('downloadLink');
downloadLink.href = URL.createObjectURL(blob);
downloadLink.download = 'output.xlsx';
downloadLink.style.display = 'block';
downloadLink.textContent = 'Download Excel File';
document.getElementById('result').innerHTML = '<p style="color: green;">Operation completed successfully! Click the download link to get the processed file.</p>';
});
</script>
</html>
Information Gathering
In addition to the above-mentioned methods, the Aspose.Cells APIs have also provided means to gather information on what sources and substitutions have been set.
- FontConfigs.fontSources method returns an array of type FontSourceBase containing the list of specified font sources. In case, no sources have been set, the FontConfigs.fontSources method will return an empty array.
- FontConfigs.fontSubstitutes(string) method accepts a parameter of type string allowing to specify the font name for which substitution has been set. In case, no substitution has been set for the specified font name then the FontConfigs.fontSubstitutes(string) method will return null.