All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.rabanti.nanoxlsx4j.lowLevel.LowLevel Maven / Gradle / Ivy

/*
 * NanoXLSX4j is a small Java library to write and read XLSX (Microsoft Excel 2007 or newer) files in an easy and native way
 * Copyright Raphael Stoeckli © 2018
 * This library is licensed under the MIT License.
 * You find a copy of the license in project folder or on: http://opensource.org/licenses/MIT
 */
package ch.rabanti.nanoxlsx4j.lowLevel;

import ch.rabanti.nanoxlsx4j.*;
import ch.rabanti.nanoxlsx4j.exception.IOException;
import ch.rabanti.nanoxlsx4j.exception.RangeException;
import ch.rabanti.nanoxlsx4j.exception.StyleException;
import ch.rabanti.nanoxlsx4j.style.*;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;


/**
 * Class for low level handling (XML, formatting, preparing of packing)
This class is only for internal use. Use the high level API (e.g. class Workbook) to manipulate data and create Excel files. * @author Raphael Stoeckli */ public class LowLevel { // ### P R I V A T E F I E L D S ### private final SortedMap sharedStrings; private int sharedStringsTotalCount; private final Workbook workbook; private boolean interceptDocuments; private HashMap interceptedDocuments; // ### G E T T E R S & S E T T E R S ### /** * Gets whether XML documents are intercepted during creation * @return If true, documents will be intercepted and stored into interceptedDocuments */ public boolean getDocumentInterception() { return interceptDocuments; } /** * Set whether XML documents are intercepted during creation * @param interceptDocuments If true, documents will be intercepted and stored into interceptedDocuments */ public void setDocumentInterception(boolean interceptDocuments) { this.interceptDocuments = interceptDocuments; if (interceptDocuments == true && this.interceptedDocuments == null) { this.interceptedDocuments = new HashMap<>(); } else if (interceptDocuments == false) { this.interceptedDocuments = null; } } /** * Gets the intercepted documents if interceptDocuments is set to true * @return HashMap with a String as key and a XML document as value */ public HashMap getInterceptedDocuments() { return interceptedDocuments; } // ### C O N S T R U C T O R S ### /** * Constructor with defined workbook object * @param workbook Workbook to process */ public LowLevel(Workbook workbook) { this.workbook = workbook; this.sharedStrings = new SortedMap(); this.sharedStringsTotalCount = 0; } // ### M E T H O D S ### /** * Method to append a simple XML tag with an enclosed value to the passed StringBuilder * @param sb StringBuilder to append * @param value Value of the XML element * @param tagName Tag name of the XML element * @param nameSpace Optional XML name space. Can be empty or null */ private void appendXMLtag(StringBuilder sb, String value, String tagName, String nameSpace) { if (Helper.isNullOrEmpty(value)) { return; } if (sb == null || Helper.isNullOrEmpty(tagName)) { return; } boolean hasNoNs = Helper.isNullOrEmpty(nameSpace); sb.append('<'); if (hasNoNs == false) { sb.append(nameSpace); sb.append(':'); } sb.append(tagName).append(">"); sb.append(escapeXMLChars(value)); sb.append(""); } /** * Method to create the app-properties (part of meta data) as XML document * @return Formatted XML document * @throws IOException Thrown in case of an error while creating the XML document */ private Document createAppPropertiesDocument() throws IOException { StringBuilder sb = new StringBuilder(); sb.append(""); sb.append(createAppString()); sb.append(""); return createXMLDocument(sb.toString(), "APPPROPERTIES"); } /** * Method to create the XML string for the app-properties document * @return String with formatted XML data */ private String createAppString() { if (this.workbook.getWorkbookMetadata() == null) { return ""; } Metadata md = this.workbook.getWorkbookMetadata(); StringBuilder sb = new StringBuilder(); appendXMLtag(sb, "0", "TotalTime", null); appendXMLtag(sb, md.getApplication(), "Application", null); appendXMLtag(sb, "0", "DocSecurity", null); appendXMLtag(sb, "false", "ScaleCrop", null); appendXMLtag(sb, md.getManager(), "Manager", null); appendXMLtag(sb, md.getCompany(), "Company", null); appendXMLtag(sb, "false", "LinksUpToDate", null); appendXMLtag(sb, "false", "SharedDoc", null); appendXMLtag(sb, md.getHyperlinkBase(), "HyperlinkBase", null); appendXMLtag(sb, "false", "HyperlinksChanged", null); appendXMLtag(sb, md.getApplicationVersion(), "AppVersion", null); return sb.toString(); } /** * Method to create the columns as XML string. This is used to define the width of columns * @param worksheet Worksheet to process * @return String with formatted XML data */ private String createColsString(Worksheet worksheet) { if (worksheet.getColumns().size() > 0) { String col; String hidden = ""; StringBuilder sb = new StringBuilder(); for (Map.Entry column : worksheet.getColumns().entrySet()) { if (column.getValue().getWidth() == worksheet.getDefaultColumnWidth() && column.getValue().isHidden() == false) { continue; } if (worksheet.getColumns().containsKey(column.getKey())) { if (worksheet.getColumns().get(column.getKey()).isHidden() == true) { hidden = " hidden=\"1\""; } } col = Integer.toString(column.getKey() + 1); // Add 1 for Address sb.append(""); } String value = sb.toString(); if (value.length() > 0) { return value; } else { return ""; } } else { return ""; } } /** * Method to create the core-properties (part of meta data) as XML document * @return Formatted XML document * @throws IOException Thrown in case of an error while creating the XML document */ private Document createCorePropertiesDocument() throws IOException { StringBuilder sb = new StringBuilder(); sb.append(""); sb.append(createCorePropertiesString()); sb.append(""); return createXMLDocument(sb.toString(),"COREPROPERTIES"); } /** * Method to create the XML string for the core-properties document * @return String with formatted XML data */ private String createCorePropertiesString() { if (this.workbook.getWorkbookMetadata() == null) { return ""; } Metadata md = this.workbook.getWorkbookMetadata(); StringBuilder sb = new StringBuilder(); appendXMLtag(sb, md.getTitle(), "title", "dc"); appendXMLtag(sb, md.getSubject(), "subject", "dc"); appendXMLtag(sb, md.getCreator(), "creator", "dc"); appendXMLtag(sb, md.getCreator(), "lastModifiedBy", "cp"); appendXMLtag(sb, md.getKeywords(), "keywords", "cp"); appendXMLtag(sb, md.getDescription(), "description", "dc"); Calendar cal = new GregorianCalendar(); DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'"); df.setCalendar(cal); Date now = cal.getTime(); String time = df.format(now); sb.append("").append(time).append(""); sb.append("").append(time).append(""); appendXMLtag(sb, md.getCategory(), "category", "cp"); appendXMLtag(sb, md.getContentStatus(), "contentStatus", "cp"); return sb.toString(); } /** * Method to create the merged cells string of the passed worksheet * @param sheet Worksheet to process * @return Formatted string with merged cell ranges */ private String createMergedCellsString(Worksheet sheet) { if (sheet.getMergedCells().size() < 1) { return ""; } Iterator> itr; Map.Entry range; StringBuilder sb = new StringBuilder(); sb.append(""); itr = sheet.getMergedCells().entrySet().iterator(); while (itr.hasNext()) { range = itr.next(); sb.append(""); } sb.append(""); return sb.toString(); } /** * Method to create the XML string for the color-MRU part of the style sheet document (recent colors) * @return String with formatted XML data */ private String createMruColorsString() { Font[] fonts = this.workbook.getStyleManager().getFonts(); Fill[] fills = this.workbook.getStyleManager().getFills(); StringBuilder sb = new StringBuilder(); List tempColors = new ArrayList<>(); for (Font font : fonts) { if (Helper.isNullOrEmpty(font.getColorValue()) == true) { continue; } if (font.getColorValue().equals(Fill.DEFAULTCOLOR)) { continue; } if (tempColors.contains(font.getColorValue()) == false) { tempColors.add(font.getColorValue()); } } for (Fill fill : fills) { if (Helper.isNullOrEmpty(fill.getBackgroundColor()) == false) { if (fill.getBackgroundColor().equals(Fill.DEFAULTCOLOR) == false) { if (tempColors.contains(fill.getBackgroundColor()) == false) { tempColors.add(fill.getBackgroundColor()); } } } if (Helper.isNullOrEmpty(fill.getForegroundColor()) == false) { if (fill.getForegroundColor().equals(Fill.DEFAULTCOLOR) == false) { if (tempColors.contains(fill.getForegroundColor()) == false) { tempColors.add(fill.getForegroundColor()); } } } } if (tempColors.size() > 0) { sb.append(""); for(int i = 0; i < tempColors.size(); i++) { sb.append(""); } sb.append(""); return sb.toString(); } else { return ""; } } /** * Method to create a row string * @param columnFields List of cells * @param worksheet Worksheet to process * @return Formatted row string */ private String createRowString(List columnFields, Worksheet worksheet) { int rowNumber = columnFields.get(0).getRowNumber(); String height = ""; String hidden = ""; if (worksheet.getRowHeights().containsKey(rowNumber)) { if (worksheet.getRowHeights().get(rowNumber) != worksheet.getDefaultRowHeight()) { height = " x14ac:dyDescent=\"0.25\" customHeight=\"1\" ht=\"" + Float.toString(worksheet.getRowHeights().get(rowNumber)) + "\""; } } if (worksheet.getHiddenRows().containsKey(rowNumber)) { if (worksheet.getHiddenRows().get(rowNumber) == true) { hidden = " hidden=\"1\""; } } int colNum = columnFields.size(); StringBuilder sb = new StringBuilder(43 * colNum); // A row string size is according to statistics (random value) 43 times the column number //StringBuilder sb = new StringBuilder(); if (colNum > 0) { sb.append(""); } else { sb.append(""); } String typeAttribute; String sValue, tValue; String value = ""; boolean bVal; Date dVal; int col = 0; Cell item; for (int i = 0; i < colNum; i++) { item = columnFields.get(i); tValue = " "; if (item.getCellStyle() != null) { sValue = " s=\"" + Integer.toString(item.getCellStyle().getInternalID()) + "\" "; } else { sValue = ""; } item.resolveCellType(); // Recalculate the type (for handling DEFAULT) if (item.getDataType() == Cell.CellType.BOOL) { typeAttribute = "b"; tValue = " t=\"" + typeAttribute + "\" "; bVal = (boolean)item.getValue(); if (bVal == true) { value = "1"; } else { value = "0"; } } // Number casting else if (item.getDataType() == Cell.CellType.NUMBER) { typeAttribute = "n"; tValue = " t=\"" + typeAttribute + "\" "; Object o = item.getValue(); if (o instanceof Byte) { value = Byte.toString((byte)item.getValue()); } else if (o instanceof BigDecimal) { value = ((BigDecimal)item.getValue()).toString(); } else if (o instanceof Double) { value = Double.toString((double)item.getValue()); } else if (o instanceof Float) { value = Float.toString((float)item.getValue());} else if (o instanceof Integer) { value = Integer.toString((int)item.getValue()); } else if (o instanceof Long) { value = Long.toString((long)item.getValue()); } else if (o instanceof Short) { value = Short.toString((short)item.getValue()); } } // Date parsing else if (item.getDataType() == Cell.CellType.DATE) { typeAttribute = "d"; dVal = (Date)item.getValue(); value = Double.toString(Helper.getOADate(dVal)); } // String parsing else { if (item.getValue() == null) { typeAttribute = "str"; value = ""; } else // handle shared Strings { // value = item.getValue().toString(); if (item.getDataType() == Cell.CellType.FORMULA) { typeAttribute = "str"; value = item.getValue().toString(); } else { typeAttribute = "s"; value = item.getValue().toString(); if (this.sharedStrings.containsKey(value) == false) { this.sharedStrings.add(value, Integer.toString(sharedStrings.size())); } value = this.sharedStrings.get(value); this.sharedStringsTotalCount++; } } tValue = " t=\"" + typeAttribute + "\" "; } if (item.getDataType() != Cell.CellType.EMPTY) { sb.append(""); if (item.getDataType() == Cell.CellType.FORMULA) { sb.append("").append(LowLevel.escapeXMLChars(item.getValue().toString())).append(""); } else { sb.append("").append(LowLevel.escapeXMLChars(value)).append(""); } sb.append(""); } else // Empty cell { sb.append(""); } col++; } sb.append(""); return sb.toString(); } /** * Method to create shared strings as XML document * @return Formatted XML document * @throws IOException Thrown in case of an error while creating the XML document */ private Document createSharedStringsDocument() throws IOException { StringBuilder sb = new StringBuilder(); sb.append(""); ArrayList keys = this.sharedStrings.getKeys(); //for (Map.Entry str : sharedStrings.entrySet()) for(int i = 0; i < keys.size(); i++) { sb.append(""); //sb.append(escapeXMLChars(str.getKey())); sb.append(escapeXMLChars(keys.get(i))); sb.append(""); } sb.append(""); return createXMLDocument(sb.toString(), "SHAREDSTRINGS"); } /** * Method to create the protection string of the passed worksheet * @param sheet Worksheet to process * @return Formatted string with protection statement of the worksheet */ private String createSheetProtectionString(Worksheet sheet) { if (sheet.isUseSheetProtection() == false) { return ""; } HashMap actualLockingValues = new HashMap<>(); if (sheet.getSheetProtectionValues().isEmpty()) { actualLockingValues.put(Worksheet.SheetProtectionValue.selectLockedCells, 1); actualLockingValues.put(Worksheet.SheetProtectionValue.selectUnlockedCells, 1); } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.objects) == false) { actualLockingValues.put(Worksheet.SheetProtectionValue.objects, 1); } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.scenarios) == false) { actualLockingValues.put(Worksheet.SheetProtectionValue.scenarios, 1); } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.selectLockedCells) == false ) { if (actualLockingValues.containsKey(Worksheet.SheetProtectionValue.selectLockedCells) == false) { actualLockingValues.put(Worksheet.SheetProtectionValue.selectLockedCells, 1); } } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.selectUnlockedCells) == false || sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.selectLockedCells) == false) { if (actualLockingValues.containsKey(Worksheet.SheetProtectionValue.selectUnlockedCells) == false) { actualLockingValues.put(Worksheet.SheetProtectionValue.selectUnlockedCells, 1); } } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.formatCells)) { actualLockingValues.put(Worksheet.SheetProtectionValue.formatCells, 0); } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.formatColumns)) { actualLockingValues.put(Worksheet.SheetProtectionValue.formatColumns, 0); } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.formatRows)) { actualLockingValues.put(Worksheet.SheetProtectionValue.formatRows, 0); } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.insertColumns)) { actualLockingValues.put(Worksheet.SheetProtectionValue.insertColumns, 0); } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.insertRows)) { actualLockingValues.put(Worksheet.SheetProtectionValue.insertRows, 0); } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.insertHyperlinks)) { actualLockingValues.put(Worksheet.SheetProtectionValue.insertHyperlinks, 0); } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.deleteColumns)) { actualLockingValues.put(Worksheet.SheetProtectionValue.deleteColumns, 0); } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.deleteRows)) { actualLockingValues.put(Worksheet.SheetProtectionValue.deleteRows, 0); } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.sort)) { actualLockingValues.put(Worksheet.SheetProtectionValue.sort, 0); } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.autoFilter)) { actualLockingValues.put(Worksheet.SheetProtectionValue.autoFilter, 0); } if (sheet.getSheetProtectionValues().contains(Worksheet.SheetProtectionValue.pivotTables)) { actualLockingValues.put(Worksheet.SheetProtectionValue.pivotTables, 0); } StringBuilder sb = new StringBuilder(); sb.append("> itr; Map.Entry item; itr = actualLockingValues.entrySet().iterator(); while (itr.hasNext()) { item = itr.next(); temp = item.getKey().name();// Note! If the enum names differs from the OOXML definitions, this method will cause invalid OOXML entries sb.append(" ").append(temp).append("=\"").append(item.getValue()).append("\""); } if (Helper.isNullOrEmpty(sheet.getSheetProtectionPassword()) == false) { String hash = generatePasswordHash(sheet.getSheetProtectionPassword()); sb.append(" password=\"").append(hash).append("\""); } sb.append(" sheet=\"1\"/>"); return sb.toString(); } /** * Method to create the XML string for the border part of the style sheet document * @return String with formatted XML data */ private String createStyleBorderString() { Border[] borderStyles = this.workbook.getStyleManager().getBorders(); StringBuilder sb = new StringBuilder(); for (Border borderStyle : borderStyles) { if (borderStyle.isDiagonalDown() == true && borderStyle.isDiagonalUp() == false) { sb.append(""); } else if (borderStyle.isDiagonalDown() == false && borderStyle.isDiagonalUp() == true) { sb.append(""); } else if (borderStyle.isDiagonalDown() == true && borderStyle.isDiagonalUp() == true) { sb.append(""); } else { sb.append(""); } if (borderStyle.getLeftStyle() != Border.StyleValue.none) { sb.append(""); if (Helper.isNullOrEmpty(borderStyle.getLeftColor()) == true) { sb.append(""); } else { sb.append(""); } sb.append(""); } else { sb.append(""); } if (borderStyle.getRightStyle() != Border.StyleValue.none) { sb.append(""); if (Helper.isNullOrEmpty(borderStyle.getRightColor()) == true) { sb.append(""); } else { sb.append(""); } sb.append(""); } else { sb.append(""); } if (borderStyle.getTopStyle() != Border.StyleValue.none) { sb.append(""); if (Helper.isNullOrEmpty(borderStyle.getTopColor()) == true) { sb.append(""); } else { sb.append(""); } sb.append(""); } else { sb.append(""); } if (borderStyle.getBottomStyle() != Border.StyleValue.none) { sb.append(""); if (Helper.isNullOrEmpty(borderStyle.getBottomColor()) == true) { sb.append(""); } else { sb.append(""); } sb.append(""); } else { sb.append(""); } if (borderStyle.getDiagonalStyle() != Border.StyleValue.none) { sb.append(""); if (Helper.isNullOrEmpty(borderStyle.getDiagonalColor()) == true) { sb.append(""); } else { sb.append(""); } sb.append(""); } else { sb.append(""); } sb.append(""); } return sb.toString(); } /** * Method to create the XML string for the fill part of the style sheet document * @return String with formatted XML data */ private String createStyleFillString() { Fill[] fillStyles = this.workbook.getStyleManager().getFills(); StringBuilder sb = new StringBuilder(); for (Fill fillStyle : fillStyles) { sb.append(""); sb.append(""); sb.append(""); sb.append(""); sb.append(""); } else if (fillStyle.getPatternFill() == Fill.PatternValue.mediumGray || fillStyle.getPatternFill() == Fill.PatternValue.lightGray || fillStyle.getPatternFill() == Fill.PatternValue.gray0625 || fillStyle.getPatternFill() == Fill.PatternValue.darkGray) { sb.append(">"); sb.append(""); if (Helper.isNullOrEmpty(fillStyle.getBackgroundColor()) == false) { sb.append(""); } sb.append(""); } else { sb.append("/>"); } sb.append(""); } return sb.toString(); } /** * Method to create the XML string for the font part of the style sheet document * @return String with formatted XML data */ private String createStyleFontString() { Font[] fontStyles = this.workbook.getStyleManager().getFonts(); StringBuilder sb = new StringBuilder(); for (Font fontStyle : fontStyles) { sb.append(""); if (fontStyle.isBold() == true) { sb.append(""); } if (fontStyle.isItalic() == true) { sb.append(""); } if (fontStyle.isUnderline() == true) { sb.append(""); } if (fontStyle.isDoubleUnderline() == true) { sb.append(""); } if (fontStyle.isStrike() == true) { sb.append(""); } if (fontStyle.getVerticalAlign() == Font.VerticalAlignValue.subscript) { sb.append(""); } else if (fontStyle.getVerticalAlign() == Font.VerticalAlignValue.superscript) { sb.append(""); } sb.append(""); if (Helper.isNullOrEmpty(fontStyle.getColorValue())) { sb.append(""); } else { sb.append(""); } sb.append(""); sb.append(""); if (fontStyle.getScheme() != Font.SchemeValue.none) { if (fontStyle.getScheme() == Font.SchemeValue.major) { sb.append(""); } else if (fontStyle.getScheme() == Font.SchemeValue.minor) { sb.append(""); } } if (Helper.isNullOrEmpty(fontStyle.getCharset()) == false) { sb.append(""); } sb.append(""); } return sb.toString(); } /** * Method to create the XML string for the number format part of the style sheet document * @return String with formatted XML data */ private String createStyleNumberFormatString() { NumberFormat[] numberFormatStyles = this.workbook.getStyleManager().getNumberFormats(); StringBuilder sb = new StringBuilder(); for (NumberFormat numberFormatStyle : numberFormatStyles) { if (numberFormatStyle.isCustomFormat() == true) { sb.append(""); } } return sb.toString(); } /** * Method to create a style sheet as XML document * @return Formatted XML document * @throws StyleException Thrown if a style was not referenced in the style sheet * @throws RangeException Thrown if a referenced cell was out of range * @throws IOException Thrown in case of an error while creating the XML document */ private Document createStyleSheetDocument() throws IOException { String bordersString = createStyleBorderString(); String fillsString = createStyleFillString(); String fontsString = createStyleFontString(); String numberFormatsString = createStyleNumberFormatString(); int numFormatCount = getNumberFormatStringCounter(); String xfsStings = createStyleXfsString(); String mruColorString = createMruColorsString(); StringBuilder sb = new StringBuilder(); sb.append(""); if (numFormatCount > 0) { sb.append(""); sb.append(numberFormatsString).append(""); } sb.append(""); sb.append(fontsString).append(""); sb.append(""); sb.append(fillsString).append(""); sb.append(""); sb.append(bordersString).append(""); sb.append(""); sb.append(xfsStings).append(""); if (this.workbook.getWorkbookMetadata() != null) { if (Helper.isNullOrEmpty(mruColorString) == false && this.workbook.getWorkbookMetadata().isUseColorMRU() == true) { sb.append(""); sb.append(mruColorString); sb.append(""); } } sb.append(""); return createXMLDocument(sb.toString(), "STYLESHEET"); } /** * Method to create the XML string for the XF part of the style sheet document * @return String with formatted XML data * @throws RangeException Thrown if a referenced cell was out of range */ private String createStyleXfsString() { Style[] styles = this.workbook.getStyleManager().getStyles(); StringBuilder sb = new StringBuilder(); StringBuilder sb2; String alignmentString, protectionString; int formatNumber, textRotation; for (Style style : styles) { textRotation = style.getCellXf().calculateInternalRotation(); alignmentString = ""; protectionString = ""; if (style.getCellXf().getHorizontalAlign() != CellXf.HorizontalAlignValue.none || style.getCellXf().getVerticalAlign() != CellXf.VerticalAlignValue.none || style.getCellXf().getAlignment() != CellXf.TextBreakValue.none || textRotation != 0) { sb2 = new StringBuilder(); sb2.append(""); // alignmentString = sb2.toString(); } if (style.getCellXf().isHidden() == true || style.getCellXf().isLocked() == true) { if (style.getCellXf().isHidden() == true && style.getCellXf().isLocked() == true) { protectionString = "