diff --git a/src/PhpSpreadsheet/Shared/Font.php b/src/PhpSpreadsheet/Shared/Font.php index aa3512ae35..9d160537a9 100644 --- a/src/PhpSpreadsheet/Shared/Font.php +++ b/src/PhpSpreadsheet/Shared/Font.php @@ -453,29 +453,26 @@ public static function getTextWidthPixelsApprox($columnText, FontStyle $font, $r $fontName = $font->getName(); $fontSize = $font->getSize(); - // Calculate column width in pixels. We assume fixed glyph width. Result varies with font name and size. + // Calculate column width in pixels. + // We assume fixed glyph width, but count double for "fullwidth" characters. + // Result varies with font name and size. switch ($fontName) { - case 'Calibri': - // value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font. - $columnWidth = (int) (8.26 * StringHelper::countCharacters($columnText)); - $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size - - break; case 'Arial': // value 8 was set because of experience in different exports at Arial 10 font. - $columnWidth = (int) (8 * StringHelper::countCharacters($columnText)); + $columnWidth = (int) (8 * StringHelper::countCharactersDbcs($columnText)); $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size break; case 'Verdana': // value 8 was found via interpolation by inspecting real Excel files with Verdana 10 font. - $columnWidth = (int) (8 * StringHelper::countCharacters($columnText)); + $columnWidth = (int) (8 * StringHelper::countCharactersDbcs($columnText)); $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size break; default: // just assume Calibri - $columnWidth = (int) (8.26 * StringHelper::countCharacters($columnText)); + // value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font. + $columnWidth = (int) (8.26 * StringHelper::countCharactersDbcs($columnText)); $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size break; diff --git a/src/PhpSpreadsheet/Shared/StringHelper.php b/src/PhpSpreadsheet/Shared/StringHelper.php index 30bd8c5fd0..c6c198e203 100644 --- a/src/PhpSpreadsheet/Shared/StringHelper.php +++ b/src/PhpSpreadsheet/Shared/StringHelper.php @@ -451,6 +451,18 @@ public static function countCharacters(string $textValue, string $encoding = 'UT return mb_strlen($textValue, $encoding); } + /** + * Get character count using mb_strwidth rather than mb_strlen. + * + * @param string $encoding Encoding + * + * @return int Character count + */ + public static function countCharactersDbcs(string $textValue, string $encoding = 'UTF-8'): int + { + return mb_strwidth($textValue, $encoding); + } + /** * Get a substring of a UTF-8 encoded string. * diff --git a/tests/PhpSpreadsheetTests/Shared/FontTest.php b/tests/PhpSpreadsheetTests/Shared/FontTest.php index 644e220050..dd6fd2e175 100644 --- a/tests/PhpSpreadsheetTests/Shared/FontTest.php +++ b/tests/PhpSpreadsheetTests/Shared/FontTest.php @@ -130,6 +130,8 @@ public function providerCalculateApproximateColumnWidth(): array [9.2834, new StyleFont(), "Hello\nWorld", 0, new StyleFont(), true, 0], [17.5671, new StyleFont(), 'PhpSpreadsheet', 0, new StyleFont(), false, 0], [19.8523, new StyleFont(), 'PhpSpreadsheet', 0, new StyleFont(), false, 1], + 'CJK characters width must be >= 43.00' => [55.2722, new StyleFont(), '如果某一列是CJK 其中的一种,这样的设置方式无效', 0, new StyleFont(), false, 0], + 'non-CJK characters width must be >= 24.73' => [31.7065, new StyleFont(), 'abcdefghijklmnopqrstuvwxyz', 0, new StyleFont(), false, 0], ]; } }