diff --git a/calc.go b/calc.go index c600aaa3..b4090c9d 100644 --- a/calc.go +++ b/calc.go @@ -59,19 +59,19 @@ const ( criteriaErr criteriaRegexp - catgoryWeightAndMass - catgoryDistance - catgoryTime - catgoryPressure - catgoryForce - catgoryEnergy - catgoryPower - catgoryMagnetism - catgoryTemperature - catgoryVolumeAndLiquidMeasure - catgoryArea - catgoryInformation - catgorySpeed + categoryWeightAndMass + categoryDistance + categoryTime + categoryPressure + categoryForce + categoryEnergy + categoryPower + categoryMagnetism + categoryTemperature + categoryVolumeAndLiquidMeasure + categoryArea + categoryInformation + categorySpeed matchModeExact = 0 matchModeMinGreater = 1 @@ -2144,177 +2144,177 @@ type conversionUnit struct { // formula function CONVERT. var conversionUnits = map[string]conversionUnit{ // weight and mass - "g": {group: catgoryWeightAndMass, allowPrefix: true}, - "sg": {group: catgoryWeightAndMass, allowPrefix: false}, - "lbm": {group: catgoryWeightAndMass, allowPrefix: false}, - "u": {group: catgoryWeightAndMass, allowPrefix: true}, - "ozm": {group: catgoryWeightAndMass, allowPrefix: false}, - "grain": {group: catgoryWeightAndMass, allowPrefix: false}, - "cwt": {group: catgoryWeightAndMass, allowPrefix: false}, - "shweight": {group: catgoryWeightAndMass, allowPrefix: false}, - "uk_cwt": {group: catgoryWeightAndMass, allowPrefix: false}, - "lcwt": {group: catgoryWeightAndMass, allowPrefix: false}, - "hweight": {group: catgoryWeightAndMass, allowPrefix: false}, - "stone": {group: catgoryWeightAndMass, allowPrefix: false}, - "ton": {group: catgoryWeightAndMass, allowPrefix: false}, - "uk_ton": {group: catgoryWeightAndMass, allowPrefix: false}, - "LTON": {group: catgoryWeightAndMass, allowPrefix: false}, - "brton": {group: catgoryWeightAndMass, allowPrefix: false}, + "g": {group: categoryWeightAndMass, allowPrefix: true}, + "sg": {group: categoryWeightAndMass, allowPrefix: false}, + "lbm": {group: categoryWeightAndMass, allowPrefix: false}, + "u": {group: categoryWeightAndMass, allowPrefix: true}, + "ozm": {group: categoryWeightAndMass, allowPrefix: false}, + "grain": {group: categoryWeightAndMass, allowPrefix: false}, + "cwt": {group: categoryWeightAndMass, allowPrefix: false}, + "shweight": {group: categoryWeightAndMass, allowPrefix: false}, + "uk_cwt": {group: categoryWeightAndMass, allowPrefix: false}, + "lcwt": {group: categoryWeightAndMass, allowPrefix: false}, + "hweight": {group: categoryWeightAndMass, allowPrefix: false}, + "stone": {group: categoryWeightAndMass, allowPrefix: false}, + "ton": {group: categoryWeightAndMass, allowPrefix: false}, + "uk_ton": {group: categoryWeightAndMass, allowPrefix: false}, + "LTON": {group: categoryWeightAndMass, allowPrefix: false}, + "brton": {group: categoryWeightAndMass, allowPrefix: false}, // distance - "m": {group: catgoryDistance, allowPrefix: true}, - "mi": {group: catgoryDistance, allowPrefix: false}, - "Nmi": {group: catgoryDistance, allowPrefix: false}, - "in": {group: catgoryDistance, allowPrefix: false}, - "ft": {group: catgoryDistance, allowPrefix: false}, - "yd": {group: catgoryDistance, allowPrefix: false}, - "ang": {group: catgoryDistance, allowPrefix: true}, - "ell": {group: catgoryDistance, allowPrefix: false}, - "ly": {group: catgoryDistance, allowPrefix: false}, - "parsec": {group: catgoryDistance, allowPrefix: false}, - "pc": {group: catgoryDistance, allowPrefix: false}, - "Pica": {group: catgoryDistance, allowPrefix: false}, - "Picapt": {group: catgoryDistance, allowPrefix: false}, - "pica": {group: catgoryDistance, allowPrefix: false}, - "survey_mi": {group: catgoryDistance, allowPrefix: false}, + "m": {group: categoryDistance, allowPrefix: true}, + "mi": {group: categoryDistance, allowPrefix: false}, + "Nmi": {group: categoryDistance, allowPrefix: false}, + "in": {group: categoryDistance, allowPrefix: false}, + "ft": {group: categoryDistance, allowPrefix: false}, + "yd": {group: categoryDistance, allowPrefix: false}, + "ang": {group: categoryDistance, allowPrefix: true}, + "ell": {group: categoryDistance, allowPrefix: false}, + "ly": {group: categoryDistance, allowPrefix: false}, + "parsec": {group: categoryDistance, allowPrefix: false}, + "pc": {group: categoryDistance, allowPrefix: false}, + "Pica": {group: categoryDistance, allowPrefix: false}, + "Picapt": {group: categoryDistance, allowPrefix: false}, + "pica": {group: categoryDistance, allowPrefix: false}, + "survey_mi": {group: categoryDistance, allowPrefix: false}, // time - "yr": {group: catgoryTime, allowPrefix: false}, - "day": {group: catgoryTime, allowPrefix: false}, - "d": {group: catgoryTime, allowPrefix: false}, - "hr": {group: catgoryTime, allowPrefix: false}, - "mn": {group: catgoryTime, allowPrefix: false}, - "min": {group: catgoryTime, allowPrefix: false}, - "sec": {group: catgoryTime, allowPrefix: true}, - "s": {group: catgoryTime, allowPrefix: true}, + "yr": {group: categoryTime, allowPrefix: false}, + "day": {group: categoryTime, allowPrefix: false}, + "d": {group: categoryTime, allowPrefix: false}, + "hr": {group: categoryTime, allowPrefix: false}, + "mn": {group: categoryTime, allowPrefix: false}, + "min": {group: categoryTime, allowPrefix: false}, + "sec": {group: categoryTime, allowPrefix: true}, + "s": {group: categoryTime, allowPrefix: true}, // pressure - "Pa": {group: catgoryPressure, allowPrefix: true}, - "p": {group: catgoryPressure, allowPrefix: true}, - "atm": {group: catgoryPressure, allowPrefix: true}, - "at": {group: catgoryPressure, allowPrefix: true}, - "mmHg": {group: catgoryPressure, allowPrefix: true}, - "psi": {group: catgoryPressure, allowPrefix: true}, - "Torr": {group: catgoryPressure, allowPrefix: true}, + "Pa": {group: categoryPressure, allowPrefix: true}, + "p": {group: categoryPressure, allowPrefix: true}, + "atm": {group: categoryPressure, allowPrefix: true}, + "at": {group: categoryPressure, allowPrefix: true}, + "mmHg": {group: categoryPressure, allowPrefix: true}, + "psi": {group: categoryPressure, allowPrefix: true}, + "Torr": {group: categoryPressure, allowPrefix: true}, // force - "N": {group: catgoryForce, allowPrefix: true}, - "dyn": {group: catgoryForce, allowPrefix: true}, - "dy": {group: catgoryForce, allowPrefix: true}, - "lbf": {group: catgoryForce, allowPrefix: false}, - "pond": {group: catgoryForce, allowPrefix: true}, + "N": {group: categoryForce, allowPrefix: true}, + "dyn": {group: categoryForce, allowPrefix: true}, + "dy": {group: categoryForce, allowPrefix: true}, + "lbf": {group: categoryForce, allowPrefix: false}, + "pond": {group: categoryForce, allowPrefix: true}, // energy - "J": {group: catgoryEnergy, allowPrefix: true}, - "e": {group: catgoryEnergy, allowPrefix: true}, - "c": {group: catgoryEnergy, allowPrefix: true}, - "cal": {group: catgoryEnergy, allowPrefix: true}, - "eV": {group: catgoryEnergy, allowPrefix: true}, - "ev": {group: catgoryEnergy, allowPrefix: true}, - "HPh": {group: catgoryEnergy, allowPrefix: false}, - "hh": {group: catgoryEnergy, allowPrefix: false}, - "Wh": {group: catgoryEnergy, allowPrefix: true}, - "wh": {group: catgoryEnergy, allowPrefix: true}, - "flb": {group: catgoryEnergy, allowPrefix: false}, - "BTU": {group: catgoryEnergy, allowPrefix: false}, - "btu": {group: catgoryEnergy, allowPrefix: false}, + "J": {group: categoryEnergy, allowPrefix: true}, + "e": {group: categoryEnergy, allowPrefix: true}, + "c": {group: categoryEnergy, allowPrefix: true}, + "cal": {group: categoryEnergy, allowPrefix: true}, + "eV": {group: categoryEnergy, allowPrefix: true}, + "ev": {group: categoryEnergy, allowPrefix: true}, + "HPh": {group: categoryEnergy, allowPrefix: false}, + "hh": {group: categoryEnergy, allowPrefix: false}, + "Wh": {group: categoryEnergy, allowPrefix: true}, + "wh": {group: categoryEnergy, allowPrefix: true}, + "flb": {group: categoryEnergy, allowPrefix: false}, + "BTU": {group: categoryEnergy, allowPrefix: false}, + "btu": {group: categoryEnergy, allowPrefix: false}, // power - "HP": {group: catgoryPower, allowPrefix: false}, - "h": {group: catgoryPower, allowPrefix: false}, - "W": {group: catgoryPower, allowPrefix: true}, - "w": {group: catgoryPower, allowPrefix: true}, - "PS": {group: catgoryPower, allowPrefix: false}, - "T": {group: catgoryMagnetism, allowPrefix: true}, - "ga": {group: catgoryMagnetism, allowPrefix: true}, + "HP": {group: categoryPower, allowPrefix: false}, + "h": {group: categoryPower, allowPrefix: false}, + "W": {group: categoryPower, allowPrefix: true}, + "w": {group: categoryPower, allowPrefix: true}, + "PS": {group: categoryPower, allowPrefix: false}, + "T": {group: categoryMagnetism, allowPrefix: true}, + "ga": {group: categoryMagnetism, allowPrefix: true}, // temperature - "C": {group: catgoryTemperature, allowPrefix: false}, - "cel": {group: catgoryTemperature, allowPrefix: false}, - "F": {group: catgoryTemperature, allowPrefix: false}, - "fah": {group: catgoryTemperature, allowPrefix: false}, - "K": {group: catgoryTemperature, allowPrefix: false}, - "kel": {group: catgoryTemperature, allowPrefix: false}, - "Rank": {group: catgoryTemperature, allowPrefix: false}, - "Reau": {group: catgoryTemperature, allowPrefix: false}, + "C": {group: categoryTemperature, allowPrefix: false}, + "cel": {group: categoryTemperature, allowPrefix: false}, + "F": {group: categoryTemperature, allowPrefix: false}, + "fah": {group: categoryTemperature, allowPrefix: false}, + "K": {group: categoryTemperature, allowPrefix: false}, + "kel": {group: categoryTemperature, allowPrefix: false}, + "Rank": {group: categoryTemperature, allowPrefix: false}, + "Reau": {group: categoryTemperature, allowPrefix: false}, // volume - "l": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: true}, - "L": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: true}, - "lt": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: true}, - "tsp": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "tspm": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "tbs": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "oz": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "cup": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "pt": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "us_pt": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "uk_pt": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "qt": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "uk_qt": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "gal": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "uk_gal": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "ang3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: true}, - "ang^3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: true}, - "barrel": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "bushel": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "in3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "in^3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "ft3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "ft^3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "ly3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "ly^3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "m3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: true}, - "m^3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: true}, - "mi3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "mi^3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "yd3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "yd^3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "Nmi3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "Nmi^3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "Pica3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "Pica^3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "Picapt3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "Picapt^3": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "GRT": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "regton": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, - "MTON": {group: catgoryVolumeAndLiquidMeasure, allowPrefix: false}, + "l": {group: categoryVolumeAndLiquidMeasure, allowPrefix: true}, + "L": {group: categoryVolumeAndLiquidMeasure, allowPrefix: true}, + "lt": {group: categoryVolumeAndLiquidMeasure, allowPrefix: true}, + "tsp": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "tspm": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "tbs": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "oz": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "cup": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "pt": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "us_pt": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "uk_pt": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "qt": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "uk_qt": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "gal": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "uk_gal": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "ang3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: true}, + "ang^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: true}, + "barrel": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "bushel": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "in3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "in^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "ft3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "ft^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "ly3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "ly^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "m3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: true}, + "m^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: true}, + "mi3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "mi^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "yd3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "yd^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "Nmi3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "Nmi^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "Pica3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "Pica^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "Picapt3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "Picapt^3": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "GRT": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "regton": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, + "MTON": {group: categoryVolumeAndLiquidMeasure, allowPrefix: false}, // area - "ha": {group: catgoryArea, allowPrefix: true}, - "uk_acre": {group: catgoryArea, allowPrefix: false}, - "us_acre": {group: catgoryArea, allowPrefix: false}, - "ang2": {group: catgoryArea, allowPrefix: true}, - "ang^2": {group: catgoryArea, allowPrefix: true}, - "ar": {group: catgoryArea, allowPrefix: true}, - "ft2": {group: catgoryArea, allowPrefix: false}, - "ft^2": {group: catgoryArea, allowPrefix: false}, - "in2": {group: catgoryArea, allowPrefix: false}, - "in^2": {group: catgoryArea, allowPrefix: false}, - "ly2": {group: catgoryArea, allowPrefix: false}, - "ly^2": {group: catgoryArea, allowPrefix: false}, - "m2": {group: catgoryArea, allowPrefix: true}, - "m^2": {group: catgoryArea, allowPrefix: true}, - "Morgen": {group: catgoryArea, allowPrefix: false}, - "mi2": {group: catgoryArea, allowPrefix: false}, - "mi^2": {group: catgoryArea, allowPrefix: false}, - "Nmi2": {group: catgoryArea, allowPrefix: false}, - "Nmi^2": {group: catgoryArea, allowPrefix: false}, - "Pica2": {group: catgoryArea, allowPrefix: false}, - "Pica^2": {group: catgoryArea, allowPrefix: false}, - "Picapt2": {group: catgoryArea, allowPrefix: false}, - "Picapt^2": {group: catgoryArea, allowPrefix: false}, - "yd2": {group: catgoryArea, allowPrefix: false}, - "yd^2": {group: catgoryArea, allowPrefix: false}, + "ha": {group: categoryArea, allowPrefix: true}, + "uk_acre": {group: categoryArea, allowPrefix: false}, + "us_acre": {group: categoryArea, allowPrefix: false}, + "ang2": {group: categoryArea, allowPrefix: true}, + "ang^2": {group: categoryArea, allowPrefix: true}, + "ar": {group: categoryArea, allowPrefix: true}, + "ft2": {group: categoryArea, allowPrefix: false}, + "ft^2": {group: categoryArea, allowPrefix: false}, + "in2": {group: categoryArea, allowPrefix: false}, + "in^2": {group: categoryArea, allowPrefix: false}, + "ly2": {group: categoryArea, allowPrefix: false}, + "ly^2": {group: categoryArea, allowPrefix: false}, + "m2": {group: categoryArea, allowPrefix: true}, + "m^2": {group: categoryArea, allowPrefix: true}, + "Morgen": {group: categoryArea, allowPrefix: false}, + "mi2": {group: categoryArea, allowPrefix: false}, + "mi^2": {group: categoryArea, allowPrefix: false}, + "Nmi2": {group: categoryArea, allowPrefix: false}, + "Nmi^2": {group: categoryArea, allowPrefix: false}, + "Pica2": {group: categoryArea, allowPrefix: false}, + "Pica^2": {group: categoryArea, allowPrefix: false}, + "Picapt2": {group: categoryArea, allowPrefix: false}, + "Picapt^2": {group: categoryArea, allowPrefix: false}, + "yd2": {group: categoryArea, allowPrefix: false}, + "yd^2": {group: categoryArea, allowPrefix: false}, // information - "byte": {group: catgoryInformation, allowPrefix: true}, - "bit": {group: catgoryInformation, allowPrefix: true}, + "byte": {group: categoryInformation, allowPrefix: true}, + "bit": {group: categoryInformation, allowPrefix: true}, // speed - "m/s": {group: catgorySpeed, allowPrefix: true}, - "m/sec": {group: catgorySpeed, allowPrefix: true}, - "m/h": {group: catgorySpeed, allowPrefix: true}, - "m/hr": {group: catgorySpeed, allowPrefix: true}, - "mph": {group: catgorySpeed, allowPrefix: false}, - "admkn": {group: catgorySpeed, allowPrefix: false}, - "kn": {group: catgorySpeed, allowPrefix: false}, + "m/s": {group: categorySpeed, allowPrefix: true}, + "m/sec": {group: categorySpeed, allowPrefix: true}, + "m/h": {group: categorySpeed, allowPrefix: true}, + "m/hr": {group: categorySpeed, allowPrefix: true}, + "mph": {group: categorySpeed, allowPrefix: false}, + "admkn": {group: categorySpeed, allowPrefix: false}, + "kn": {group: categorySpeed, allowPrefix: false}, } // unitConversions maps details of the Units of measure conversion factors, // organised by group. var unitConversions = map[byte]map[string]float64{ // conversion uses gram (g) as an intermediate unit - catgoryWeightAndMass: { + categoryWeightAndMass: { "g": 1, "sg": 6.85217658567918e-05, "lbm": 2.20462262184878e-03, @@ -2333,7 +2333,7 @@ var unitConversions = map[byte]map[string]float64{ "brton": 9.84206527611061e-07, }, // conversion uses meter (m) as an intermediate unit - catgoryDistance: { + categoryDistance: { "m": 1, "mi": 6.21371192237334e-04, "Nmi": 5.39956803455724e-04, @@ -2351,7 +2351,7 @@ var unitConversions = map[byte]map[string]float64{ "survey_mi": 6.21369949494950e-04, }, // conversion uses second (s) as an intermediate unit - catgoryTime: { + categoryTime: { "yr": 3.16880878140289e-08, "day": 1.15740740740741e-05, "d": 1.15740740740741e-05, @@ -2362,7 +2362,7 @@ var unitConversions = map[byte]map[string]float64{ "s": 1, }, // conversion uses Pascal (Pa) as an intermediate unit - catgoryPressure: { + categoryPressure: { "Pa": 1, "p": 1, "atm": 9.86923266716013e-06, @@ -2372,7 +2372,7 @@ var unitConversions = map[byte]map[string]float64{ "Torr": 7.50061682704170e-03, }, // conversion uses Newton (N) as an intermediate unit - catgoryForce: { + categoryForce: { "N": 1, "dyn": 1.0e+5, "dy": 1.0e+5, @@ -2380,7 +2380,7 @@ var unitConversions = map[byte]map[string]float64{ "pond": 1.01971621297793e+02, }, // conversion uses Joule (J) as an intermediate unit - catgoryEnergy: { + categoryEnergy: { "J": 1, "e": 9.99999519343231e+06, "c": 2.39006249473467e-01, @@ -2396,7 +2396,7 @@ var unitConversions = map[byte]map[string]float64{ "btu": 9.47815067349015e-04, }, // conversion uses Horsepower (HP) as an intermediate unit - catgoryPower: { + categoryPower: { "HP": 1, "h": 1, "W": 7.45699871582270e+02, @@ -2404,12 +2404,12 @@ var unitConversions = map[byte]map[string]float64{ "PS": 1.01386966542400e+00, }, // conversion uses Tesla (T) as an intermediate unit - catgoryMagnetism: { + categoryMagnetism: { "T": 1, "ga": 10000, }, // conversion uses litre (l) as an intermediate unit - catgoryVolumeAndLiquidMeasure: { + categoryVolumeAndLiquidMeasure: { "l": 1, "L": 1, "lt": 1, @@ -2452,7 +2452,7 @@ var unitConversions = map[byte]map[string]float64{ "MTON": 8.82866668037215e-04, }, // conversion uses hectare (ha) as an intermediate unit - catgoryArea: { + categoryArea: { "ha": 1, "uk_acre": 2.47105381467165e+00, "us_acre": 2.47104393046628e+00, @@ -2480,12 +2480,12 @@ var unitConversions = map[byte]map[string]float64{ "yd^2": 1.19599004630108e+04, }, // conversion uses bit (bit) as an intermediate unit - catgoryInformation: { + categoryInformation: { "bit": 1, "byte": 0.125, }, // conversion uses Meters per Second (m/s) as an intermediate unit - catgorySpeed: { + categorySpeed: { "m/s": 1, "m/sec": 1, "m/h": 3.60e+03, @@ -2639,7 +2639,7 @@ func (fn *formulaFuncs) CONVERT(argsList *list.List) formulaArg { return newNumberFormulaArg(val / fromMultiplier) } else if fromUOM == toUOM { return newNumberFormulaArg(val / toMultiplier) - } else if fromCategory == catgoryTemperature { + } else if fromCategory == categoryTemperature { return newNumberFormulaArg(convertTemperature(fromUOM, toUOM, val)) } fromConversion := unitConversions[fromCategory][fromUOM] @@ -13607,7 +13607,7 @@ func (fn *formulaFuncs) replace(name string, argsList *list.List) formulaArg { if argsList.Len() != 4 { return newErrorFormulaArg(formulaErrorVALUE, fmt.Sprintf("%s requires 4 arguments", name)) } - oldText, newText := argsList.Front().Value.(formulaArg).Value(), argsList.Back().Value.(formulaArg).Value() + sourceText, targetText := argsList.Front().Value.(formulaArg).Value(), argsList.Back().Value.(formulaArg).Value() startNumArg, numCharsArg := argsList.Front().Next().Value.(formulaArg).ToNumber(), argsList.Front().Next().Next().Value.(formulaArg).ToNumber() if startNumArg.Type != ArgNumber { return startNumArg @@ -13615,18 +13615,18 @@ func (fn *formulaFuncs) replace(name string, argsList *list.List) formulaArg { if numCharsArg.Type != ArgNumber { return numCharsArg } - oldTextLen, startIdx := len(oldText), int(startNumArg.Number) - if startIdx > oldTextLen { - startIdx = oldTextLen + 1 + sourceTextLen, startIdx := len(sourceText), int(startNumArg.Number) + if startIdx > sourceTextLen { + startIdx = sourceTextLen + 1 } endIdx := startIdx + int(numCharsArg.Number) - if endIdx > oldTextLen { - endIdx = oldTextLen + 1 + if endIdx > sourceTextLen { + endIdx = sourceTextLen + 1 } if startIdx < 1 || endIdx < 1 { return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE) } - result := oldText[:startIdx-1] + newText + oldText[endIdx-1:] + result := sourceText[:startIdx-1] + targetText + sourceText[endIdx-1:] return newStringFormulaArg(result) } @@ -13683,10 +13683,10 @@ func (fn *formulaFuncs) SUBSTITUTE(argsList *list.List) formulaArg { if argsList.Len() != 3 && argsList.Len() != 4 { return newErrorFormulaArg(formulaErrorVALUE, "SUBSTITUTE requires 3 or 4 arguments") } - text, oldText := argsList.Front().Value.(formulaArg), argsList.Front().Next().Value.(formulaArg) - newText, instanceNum := argsList.Front().Next().Next().Value.(formulaArg), 0 + text, sourceText := argsList.Front().Value.(formulaArg), argsList.Front().Next().Value.(formulaArg) + targetText, instanceNum := argsList.Front().Next().Next().Value.(formulaArg), 0 if argsList.Len() == 3 { - return newStringFormulaArg(strings.ReplaceAll(text.Value(), oldText.Value(), newText.Value())) + return newStringFormulaArg(strings.ReplaceAll(text.Value(), sourceText.Value(), targetText.Value())) } instanceNumArg := argsList.Back().Value.(formulaArg).ToNumber() if instanceNumArg.Type != ArgNumber { @@ -13696,10 +13696,10 @@ func (fn *formulaFuncs) SUBSTITUTE(argsList *list.List) formulaArg { if instanceNum < 1 { return newErrorFormulaArg(formulaErrorVALUE, "instance_num should be > 0") } - str, oldTextLen, count, chars, pos := text.Value(), len(oldText.Value()), instanceNum, 0, -1 + str, sourceTextLen, count, chars, pos := text.Value(), len(sourceText.Value()), instanceNum, 0, -1 for { count-- - index := strings.Index(str, oldText.Value()) + index := strings.Index(str, sourceText.Value()) if index == -1 { pos = -1 break @@ -13708,7 +13708,7 @@ func (fn *formulaFuncs) SUBSTITUTE(argsList *list.List) formulaArg { if count == 0 { break } - idx := oldTextLen + index + idx := sourceTextLen + index chars += idx str = str[idx:] } @@ -13716,8 +13716,8 @@ func (fn *formulaFuncs) SUBSTITUTE(argsList *list.List) formulaArg { if pos == -1 { return newStringFormulaArg(text.Value()) } - pre, post := text.Value()[:pos], text.Value()[pos+oldTextLen:] - return newStringFormulaArg(pre + newText.Value() + post) + pre, post := text.Value()[:pos], text.Value()[pos+sourceTextLen:] + return newStringFormulaArg(pre + targetText.Value() + post) } // TEXTJOIN function joins together a series of supplied text strings into one diff --git a/drawing.go b/drawing.go index 0bd8604b..4fe575ba 100644 --- a/drawing.go +++ b/drawing.go @@ -91,7 +91,7 @@ func (f *File) addChart(opts *chartOptions, comboCharts []*chartOptions) { Cs: &aCs{ Typeface: "+mn-cs", }, - Latin: &aLatin{ + Latin: &xlsxCTTextFont{ Typeface: "+mn-lt", }, }, @@ -1168,7 +1168,7 @@ func (f *File) drawPlotAreaTxPr(opts *chartAxisOptions) *cTxPr { LumOff: &attrValInt{Val: intPtr(85000)}, }, }, - Latin: &aLatin{Typeface: "+mn-lt"}, + Latin: &xlsxCTTextFont{Typeface: "+mn-lt"}, Ea: &aEa{Typeface: "+mn-ea"}, Cs: &aCs{Typeface: "+mn-cs"}, }, diff --git a/errors.go b/errors.go index 6a23a2e9..f486ad4d 100644 --- a/errors.go +++ b/errors.go @@ -93,6 +93,12 @@ func newStreamSetRowError(row int) error { return fmt.Errorf("row %d has already been written", row) } +// newViewIdxError defined the error message on receiving a invalid sheet view +// index. +func newViewIdxError(viewIndex int) error { + return fmt.Errorf("view index %d out of range", viewIndex) +} + var ( // ErrStreamSetColWidth defined the error message on set column width in // stream writing mode. diff --git a/file.go b/file.go index 1469af09..fe5decaa 100644 --- a/file.go +++ b/file.go @@ -182,6 +182,7 @@ func (f *File) writeToZip(zw *zip.Writer) error { _ = f.sharedStringsLoader() f.sharedStringsWriter() f.styleSheetWriter() + f.themeWriter() for path, stream := range f.streams { fi, err := zw.Create(path) diff --git a/lib.go b/lib.go index 685571c4..16170a71 100644 --- a/lib.go +++ b/lib.go @@ -626,12 +626,12 @@ func getXMLNamespace(space string, attr []xml.Attr) string { // replaceNameSpaceBytes provides a function to replace the XML root element // attribute by the given component part path and XML content. func (f *File) replaceNameSpaceBytes(path string, contentMarshal []byte) []byte { - oldXmlns := []byte(`xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`) - newXmlns := []byte(templateNamespaceIDMap) + sourceXmlns := []byte(`xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">`) + targetXmlns := []byte(templateNamespaceIDMap) if attr, ok := f.xmlAttr[path]; ok { - newXmlns = []byte(genXMLNamespace(attr)) + targetXmlns = []byte(genXMLNamespace(attr)) } - return bytesReplace(contentMarshal, oldXmlns, bytes.ReplaceAll(newXmlns, []byte(" mc:Ignorable=\"r\""), []byte{}), -1) + return bytesReplace(contentMarshal, sourceXmlns, bytes.ReplaceAll(targetXmlns, []byte(" mc:Ignorable=\"r\""), []byte{}), -1) } // addNameSpaces provides a function to add an XML attribute by the given diff --git a/merge.go b/merge.go index 04dc493d..a839b96d 100644 --- a/merge.go +++ b/merge.go @@ -17,7 +17,11 @@ import "strings" func (mc *xlsxMergeCell) Rect() ([]int, error) { var err error if mc.rect == nil { - mc.rect, err = rangeRefToCoordinates(mc.Ref) + mergedCellsRef := mc.Ref + if !strings.Contains(mergedCellsRef, ":") { + mergedCellsRef += ":" + mergedCellsRef + } + mc.rect, err = rangeRefToCoordinates(mergedCellsRef) } return mc.rect, err } @@ -105,7 +109,11 @@ func (f *File) UnmergeCell(sheet, hCell, vCell string) error { if mergeCell == nil { continue } - rect2, _ := rangeRefToCoordinates(mergeCell.Ref) + mergedCellsRef := mergeCell.Ref + if !strings.Contains(mergedCellsRef, ":") { + mergedCellsRef += ":" + mergedCellsRef + } + rect2, _ := rangeRefToCoordinates(mergedCellsRef) if isOverlap(rect1, rect2) { continue } diff --git a/merge_test.go b/merge_test.go index 6977c5ac..e0b92103 100644 --- a/merge_test.go +++ b/merge_test.go @@ -185,7 +185,7 @@ func TestUnmergeCell(t *testing.T) { ws, ok = f.Sheet.Load("xl/worksheets/sheet1.xml") assert.True(t, ok) ws.(*xlsxWorksheet).MergeCells = &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A1"}}} - assert.EqualError(t, f.UnmergeCell("Sheet1", "A2", "B3"), ErrParameterInvalid.Error()) + assert.NoError(t, f.UnmergeCell("Sheet1", "A2", "B3")) ws, ok = f.Sheet.Load("xl/worksheets/sheet1.xml") assert.True(t, ok) @@ -194,6 +194,6 @@ func TestUnmergeCell(t *testing.T) { } func TestFlatMergedCells(t *testing.T) { - ws := &xlsxWorksheet{MergeCells: &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A1"}}}} - assert.EqualError(t, flatMergedCells(ws, [][]*xlsxMergeCell{}), ErrParameterInvalid.Error()) + ws := &xlsxWorksheet{MergeCells: &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: ""}}}} + assert.EqualError(t, flatMergedCells(ws, [][]*xlsxMergeCell{}), "cannot convert cell \"\" to coordinates: invalid cell name \"\"") } diff --git a/rows.go b/rows.go index 4f05f243..5b21f294 100644 --- a/rows.go +++ b/rows.go @@ -744,8 +744,8 @@ func checkRow(ws *xlsxWorksheet) error { } if colCount < lastCol { - oldList := rowData.C - newList := make([]xlsxC, 0, lastCol) + sourceList := rowData.C + targetList := make([]xlsxC, 0, lastCol) rowData.C = ws.SheetData.Row[rowIdx].C[:0] @@ -754,13 +754,13 @@ func checkRow(ws *xlsxWorksheet) error { if err != nil { return err } - newList = append(newList, xlsxC{R: cellName}) + targetList = append(targetList, xlsxC{R: cellName}) } - rowData.C = newList + rowData.C = targetList - for colIdx := range oldList { - colData := &oldList[colIdx] + for colIdx := range sourceList { + colData := &sourceList[colIdx] colNum, _, err := CellNameToCoordinates(colData.R) if err != nil { return err diff --git a/shape.go b/shape.go index e3c6c8bc..9f250d79 100644 --- a/shape.go +++ b/shape.go @@ -418,7 +418,7 @@ func (f *File) addDrawingShape(sheet, drawingXML, cell string, opts *shapeOption AltLang: "en-US", U: u, Sz: p.Font.Size * 100, - Latin: &aLatin{Typeface: p.Font.Family}, + Latin: &xlsxCTTextFont{Typeface: p.Font.Family}, }, T: text, }, diff --git a/sheet.go b/sheet.go index ecd39f06..070b47d1 100644 --- a/sheet.go +++ b/sheet.go @@ -243,9 +243,9 @@ func (f *File) relsWriter() { // strict requirements about the structure of the input XML. This function is // a horrible hack to fix that after the XML marshalling is completed. func replaceRelationshipsBytes(content []byte) []byte { - oldXmlns := []byte(`xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships`) - newXmlns := []byte("r") - return bytesReplace(content, oldXmlns, newXmlns, -1) + sourceXmlns := []byte(`xmlns:relationships="http://schemas.openxmlformats.org/officeDocument/2006/relationships" relationships`) + targetXmlns := []byte("r") + return bytesReplace(content, sourceXmlns, targetXmlns, -1) } // SetActiveSheet provides a function to set the default active sheet of the @@ -1623,7 +1623,7 @@ func (f *File) InsertPageBreak(sheet, cell string) error { if row != 0 && rowBrk == -1 { ws.RowBreaks.Brk = append(ws.RowBreaks.Brk, &xlsxBrk{ ID: row, - Max: 16383, + Max: MaxColumns - 1, Man: true, }) ws.RowBreaks.ManualBreakCount++ @@ -1631,7 +1631,7 @@ func (f *File) InsertPageBreak(sheet, cell string) error { if col != 0 && colBrk == -1 { ws.ColBreaks.Brk = append(ws.ColBreaks.Brk, &xlsxBrk{ ID: col, - Max: 1048575, + Max: TotalRows - 1, Man: true, }) ws.ColBreaks.ManualBreakCount++ diff --git a/sheetview.go b/sheetview.go index a47d5100..9845942d 100644 --- a/sheetview.go +++ b/sheetview.go @@ -11,8 +11,6 @@ package excelize -import "fmt" - // getSheetView returns the SheetView object func (f *File) getSheetView(sheet string, viewIndex int) (*xlsxSheetView, error) { ws, err := f.workSheetReader(sheet) @@ -26,11 +24,11 @@ func (f *File) getSheetView(sheet string, viewIndex int) (*xlsxSheetView, error) } if viewIndex < 0 { if viewIndex < -len(ws.SheetViews.SheetView) { - return nil, fmt.Errorf("view index %d out of range", viewIndex) + return nil, newViewIdxError(viewIndex) } viewIndex = len(ws.SheetViews.SheetView) + viewIndex } else if viewIndex >= len(ws.SheetViews.SheetView) { - return nil, fmt.Errorf("view index %d out of range", viewIndex) + return nil, newViewIdxError(viewIndex) } return &(ws.SheetViews.SheetView[viewIndex]), err diff --git a/styles.go b/styles.go index 15de5f1a..f7d00e19 100644 --- a/styles.go +++ b/styles.go @@ -1057,6 +1057,15 @@ func (f *File) styleSheetWriter() { } } +// themeWriter provides a function to save xl/theme/theme1.xml after serialize +// structure. +func (f *File) themeWriter() { + if f.Theme != nil { + output, _ := xml.Marshal(f.Theme) + f.saveFileList(defaultXMLPathTheme, f.replaceNameSpaceBytes(defaultXMLPathTheme, output)) + } +} + // sharedStringsWriter provides a function to save xl/sharedStrings.xml after // serialize structure. func (f *File) sharedStringsWriter() { @@ -3311,11 +3320,11 @@ func getPaletteColor(color string) string { // themeReader provides a function to get the pointer to the xl/theme/theme1.xml // structure after deserialization. func (f *File) themeReader() *xlsxTheme { - var ( - err error - theme xlsxTheme - ) - if err = f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML("xl/theme/theme1.xml")))). + if _, ok := f.Pkg.Load(defaultXMLPathTheme); !ok { + return nil + } + theme := xlsxTheme{XMLNSa: NameSpaceDrawingML.Value, XMLNSr: SourceRelationship.Value} + if err := f.xmlNewDecoder(bytes.NewReader(namespaceStrictToTransitional(f.readXML(defaultXMLPathTheme)))). Decode(&theme); err != nil && err != io.EOF { log.Printf("xml decoder error: %s", err) } diff --git a/styles_test.go b/styles_test.go index f27c9a20..487a6df6 100644 --- a/styles_test.go +++ b/styles_test.go @@ -334,8 +334,8 @@ func TestStylesReader(t *testing.T) { func TestThemeReader(t *testing.T) { f := NewFile() // Test read theme with unsupported charset. - f.Pkg.Store("xl/theme/theme1.xml", MacintoshCyrillicCharset) - assert.EqualValues(t, new(xlsxTheme), f.themeReader()) + f.Pkg.Store(defaultXMLPathTheme, MacintoshCyrillicCharset) + assert.EqualValues(t, &xlsxTheme{XMLNSa: NameSpaceDrawingML.Value, XMLNSr: SourceRelationship.Value}, f.themeReader()) } func TestSetCellStyle(t *testing.T) { diff --git a/templates.go b/templates.go index 1e46b561..c8233c18 100644 --- a/templates.go +++ b/templates.go @@ -21,6 +21,7 @@ const ( defaultXMLPathCalcChain = "xl/calcChain.xml" defaultXMLPathSharedStrings = "xl/sharedStrings.xml" defaultXMLPathStyles = "xl/styles.xml" + defaultXMLPathTheme = "xl/theme/theme1.xml" defaultXMLPathWorkbook = "xl/workbook.xml" defaultTempFileSST = "sharedStrings" ) diff --git a/xmlChart.go b/xmlChart.go index 2ebcdefe..5165ea09 100644 --- a/xmlChart.go +++ b/xmlChart.go @@ -171,12 +171,11 @@ type aEa struct { Typeface string `xml:"typeface,attr"` } -// aLatin (Latin Font) directly maps the a:latin element. This element -// specifies that a Latin font be used for a specific run of text. This font is -// specified with a typeface attribute much like the others but is specifically -// classified as a Latin font. -type aLatin struct { - Typeface string `xml:"typeface,attr"` +type xlsxCTTextFont struct { + Typeface string `xml:"typeface,attr"` + Panose string `xml:"panose,attr,omitempty"` + PitchFamily string `xml:"pitchFamily,attr,omitempty"` + Charset string `xml:"Charset,attr,omitempty"` } // aR directly maps the a:r element. @@ -191,29 +190,29 @@ type aR struct { // properties are defined as direct formatting, since they are directly applied // to the run and supersede any formatting from styles. type aRPr struct { - AltLang string `xml:"altLang,attr,omitempty"` - B bool `xml:"b,attr"` - Baseline int `xml:"baseline,attr"` - Bmk string `xml:"bmk,attr,omitempty"` - Cap string `xml:"cap,attr,omitempty"` - Dirty bool `xml:"dirty,attr,omitempty"` - Err bool `xml:"err,attr,omitempty"` - I bool `xml:"i,attr"` - Kern int `xml:"kern,attr"` - Kumimoji bool `xml:"kumimoji,attr,omitempty"` - Lang string `xml:"lang,attr,omitempty"` - NoProof bool `xml:"noProof,attr,omitempty"` - NormalizeH bool `xml:"normalizeH,attr,omitempty"` - SmtClean bool `xml:"smtClean,attr,omitempty"` - SmtID uint64 `xml:"smtId,attr,omitempty"` - Spc int `xml:"spc,attr"` - Strike string `xml:"strike,attr,omitempty"` - Sz float64 `xml:"sz,attr,omitempty"` - U string `xml:"u,attr,omitempty"` - SolidFill *aSolidFill `xml:"a:solidFill"` - Latin *aLatin `xml:"a:latin"` - Ea *aEa `xml:"a:ea"` - Cs *aCs `xml:"a:cs"` + AltLang string `xml:"altLang,attr,omitempty"` + B bool `xml:"b,attr"` + Baseline int `xml:"baseline,attr"` + Bmk string `xml:"bmk,attr,omitempty"` + Cap string `xml:"cap,attr,omitempty"` + Dirty bool `xml:"dirty,attr,omitempty"` + Err bool `xml:"err,attr,omitempty"` + I bool `xml:"i,attr"` + Kern int `xml:"kern,attr"` + Kumimoji bool `xml:"kumimoji,attr,omitempty"` + Lang string `xml:"lang,attr,omitempty"` + NoProof bool `xml:"noProof,attr,omitempty"` + NormalizeH bool `xml:"normalizeH,attr,omitempty"` + SmtClean bool `xml:"smtClean,attr,omitempty"` + SmtID uint64 `xml:"smtId,attr,omitempty"` + Spc int `xml:"spc,attr"` + Strike string `xml:"strike,attr,omitempty"` + Sz float64 `xml:"sz,attr,omitempty"` + U string `xml:"u,attr,omitempty"` + SolidFill *aSolidFill `xml:"a:solidFill"` + Latin *xlsxCTTextFont `xml:"a:latin"` + Ea *aEa `xml:"a:ea"` + Cs *aCs `xml:"a:cs"` } // cSpPr (Shape Properties) directly maps the spPr element. This element diff --git a/xmlDrawing.go b/xmlDrawing.go index 5b4628b5..dc48ccc0 100644 --- a/xmlDrawing.go +++ b/xmlDrawing.go @@ -159,6 +159,7 @@ var IndexedColorMapping = []string{ "00CCFF", "CCFFFF", "CCFFCC", "FFFF99", "99CCFF", "FF99CC", "CC99FF", "FFCC99", "3366FF", "33CCCC", "99CC00", "FFCC00", "FF9900", "FF6600", "666699", "969696", "003366", "339966", "003300", "333300", "993300", "993366", "333399", "333333", + "000000", "FFFFFF", } // supportedImageTypes defined supported image types. diff --git a/xmlTheme.go b/xmlTheme.go index 6b9e207c..80bb3afa 100644 --- a/xmlTheme.go +++ b/xmlTheme.go @@ -16,12 +16,59 @@ import "encoding/xml" // xlsxTheme directly maps the theme element in the namespace // http://schemas.openxmlformats.org/drawingml/2006/main type xlsxTheme struct { - ThemeElements xlsxThemeElements `xml:"themeElements"` + XMLName xml.Name `xml:"http://schemas.openxmlformats.org/drawingml/2006/main theme"` + XMLNSa string `xml:"xmlns:a,attr"` + XMLNSr string `xml:"xmlns:r,attr"` + Name string `xml:"name,attr"` + ThemeElements xlsxBaseStyles `xml:"themeElements"` ObjectDefaults xlsxObjectDefaults `xml:"objectDefaults"` ExtraClrSchemeLst xlsxExtraClrSchemeLst `xml:"extraClrSchemeLst"` + CustClrLst *xlsxInnerXML `xml:"custClrLst"` ExtLst *xlsxExtLst `xml:"extLst"` } +// xlsxBaseStyles defines the theme elements for a theme, and is the workhorse +// of the theme. The bulk of the shared theme information that is used by a +// given document is defined here. Within this complex type is defined a color +// scheme, a font scheme, and a style matrix (format scheme) that defines +// different formatting options for different pieces of a document. +type xlsxBaseStyles struct { + ClrScheme xlsxColorScheme `xml:"clrScheme"` + FontScheme xlsxFontScheme `xml:"fontScheme"` + FmtScheme xlsxStyleMatrix `xml:"fmtScheme"` + ExtLst *xlsxExtLst `xml:"extLst"` +} + +// xlsxCTColor holds the actual color values that are to be applied to a given +// diagram and how those colors are to be applied. +type xlsxCTColor struct { + ScrgbClr *xlsxInnerXML `xml:"scrgbClr"` + SrgbClr *attrValString `xml:"srgbClr"` + HslClr *xlsxInnerXML `xml:"hslClr"` + SysClr *xlsxSysClr `xml:"sysClr"` + SchemeClr *xlsxInnerXML `xml:"schemeClr"` + PrstClr *xlsxInnerXML `xml:"prstClr"` +} + +// xlsxColorScheme defines a set of colors for the theme. The set of colors +// consists of twelve color slots that can each hold a color of choice. +type xlsxColorScheme struct { + Name string `xml:"name,attr"` + Dk1 xlsxCTColor `xml:"dk1"` + Lt1 xlsxCTColor `xml:"lt1"` + Dk2 xlsxCTColor `xml:"dk2"` + Lt2 xlsxCTColor `xml:"lt2"` + Accent1 xlsxCTColor `xml:"accent1"` + Accent2 xlsxCTColor `xml:"accent2"` + Accent3 xlsxCTColor `xml:"accent3"` + Accent4 xlsxCTColor `xml:"accent4"` + Accent5 xlsxCTColor `xml:"accent5"` + Accent6 xlsxCTColor `xml:"accent6"` + Hlink xlsxCTColor `xml:"hlink"` + FolHlink xlsxCTColor `xml:"folHlink"` + ExtLst *xlsxExtLst `xml:"extLst"` +} + // objectDefaults element allows for the definition of default shape, line, // and textbox formatting properties. An application can use this information // to format a shape (or text) initially on insertion into a document. @@ -35,24 +82,24 @@ type xlsxExtraClrSchemeLst struct { ExtraClrSchemeLst string `xml:",innerxml"` } -// xlsxThemeElements directly maps the element defines the theme formatting -// options for the theme and is the workhorse of the theme. This is where the -// bulk of the shared theme information is contained and used by a document. -// This element contains the color scheme, font scheme, and format scheme -// elements which define the different formatting aspects of what a theme -// defines. -type xlsxThemeElements struct { - ClrScheme xlsxClrScheme `xml:"clrScheme"` - FontScheme xlsxFontScheme `xml:"fontScheme"` - FmtScheme xlsxFmtScheme `xml:"fmtScheme"` +// xlsxCTSupplementalFont defines an additional font that is used for language +// specific fonts in themes. For example, one can specify a font that gets used +// only within the Japanese language context. +type xlsxCTSupplementalFont struct { + Script string `xml:"script,attr"` + Typeface string `xml:"typeface,attr"` } -// xlsxClrScheme element specifies the theme color, stored in the document's -// Theme part to which the value of this theme color shall be mapped. This -// mapping enables multiple theme colors to be chained together. -type xlsxClrScheme struct { - Name string `xml:"name,attr"` - Children []xlsxClrSchemeEl `xml:",any"` +// xlsxFontCollection defines a major and minor font which is used in the font +// scheme. A font collection consists of a font definition for Latin, East +// Asian, and complex script. On top of these three definitions, one can also +// define a font for use in a specific language or languages. +type xlsxFontCollection struct { + Latin *xlsxCTTextFont `xml:"latin"` + Ea *xlsxCTTextFont `xml:"ea"` + Cs *xlsxCTTextFont `xml:"cs"` + Font []xlsxCTSupplementalFont `xml:"font"` + ExtLst *xlsxExtLst `xml:"extLst"` } // xlsxFontScheme element defines the font scheme within the theme. The font @@ -61,34 +108,19 @@ type xlsxClrScheme struct { // document, and the minor font corresponds well with the normal text or // paragraph areas. type xlsxFontScheme struct { - Name string `xml:"name,attr"` - MajorFont xlsxMajorFont `xml:"majorFont"` - MinorFont xlsxMinorFont `xml:"minorFont"` - ExtLst *xlsxExtLst `xml:"extLst"` + Name string `xml:"name,attr"` + MajorFont xlsxFontCollection `xml:"majorFont"` + MinorFont xlsxFontCollection `xml:"minorFont"` + ExtLst *xlsxExtLst `xml:"extLst"` } -// xlsxMajorFont element defines the set of major fonts which are to be used -// under different languages or locals. -type xlsxMajorFont struct { - Children []xlsxFontSchemeEl `xml:",any"` -} - -// xlsxMinorFont element defines the set of minor fonts that are to be used -// under different languages or locals. -type xlsxMinorFont struct { - Children []xlsxFontSchemeEl `xml:",any"` -} - -// xlsxFmtScheme element contains the background fill styles, effect styles, -// fill styles, and line styles which define the style matrix for a theme. The -// style matrix consists of subtle, moderate, and intense fills, lines, and -// effects. The background fills are not generally thought of to directly be -// associated with the matrix, but do play a role in the style of the overall -// document. Usually, a given object chooses a single line style, a single -// fill style, and a single effect style in order to define the overall final -// look of the object. -type xlsxFmtScheme struct { - Name string `xml:"name,attr"` +// xlsxStyleMatrix defines a set of formatting options, which can be referenced +// by documents that apply a certain style to a given part of an object. For +// example, in a given shape, say a rectangle, one can reference a themed line +// style, themed effect, and themed fill that would be theme specific and +// change when the theme is changed. +type xlsxStyleMatrix struct { + Name string `xml:"name,attr,omitempty"` FillStyleLst xlsxFillStyleLst `xml:"fillStyleLst"` LnStyleLst xlsxLnStyleLst `xml:"lnStyleLst"` EffectStyleLst xlsxEffectStyleLst `xml:"effectStyleLst"` @@ -123,26 +155,6 @@ type xlsxBgFillStyleLst struct { BgFillStyleLst string `xml:",innerxml"` } -// xlsxClrScheme specifies the theme color, stored in the document's Theme -// part to which the value of this theme color shall be mapped. This mapping -// enables multiple theme colors to be chained together. -type xlsxClrSchemeEl struct { - XMLName xml.Name - SysClr *xlsxSysClr `xml:"sysClr"` - SrgbClr *attrValString `xml:"srgbClr"` -} - -// xlsxFontSchemeEl directly maps the major and minor font of the style's font -// scheme. -type xlsxFontSchemeEl struct { - XMLName xml.Name - Script string `xml:"script,attr,omitempty"` - Typeface string `xml:"typeface,attr"` - Panose string `xml:"panose,attr,omitempty"` - PitchFamily string `xml:"pitchFamily,attr,omitempty"` - Charset string `xml:"charset,attr,omitempty"` -} - // xlsxSysClr element specifies a color bound to predefined operating system // elements. type xlsxSysClr struct {