Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). Thia is a

- Limited Printarea support for Html/Pdf. [Issue #3941](https://github.com/PHPOffice/PhpSpreadsheet/issues/3941) [PR #4711](https://github.com/PHPOffice/PhpSpreadsheet/pull/4711)
- Implement missing `INFO` function. [PR #4709](https://github.com/PHPOffice/PhpSpreadsheet/pull/4709)
- Implement missing `BAHTTEXT` function. [PR #4715](https://github.com/PHPOffice/PhpSpreadsheet/pull/4715)

### Removed

Expand Down
2 changes: 1 addition & 1 deletion docs/references/function-list-by-category.md
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ Excel Function | PhpSpreadsheet Function
-------------------------|--------------------------------------
ARRAYTOTEXT | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Text::fromArray
ASC | **Not yet Implemented**
BAHTTEXT | **Not yet Implemented**
BAHTTEXT | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Thai::getBahtText
CHAR | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CharacterConvert::character
CLEAN | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Trim::nonPrintable
CODE | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CharacterConvert::code
Expand Down
2 changes: 1 addition & 1 deletion docs/references/function-list-by-name-compact.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ AVERAGEIFS | STATISTICAL | Statistical\Conditional::AVER

Excel Function | Category | PhpSpreadsheet Function
-------------------------|-----------------------|--------------------------------------
BAHTTEXT | TEXT_AND_DATA | **Not yet Implemented**
BAHTTEXT | TEXT_AND_DATA | TextData\Thai::getBahtText
BASE | MATH_AND_TRIG | MathTrig\Base::evaluate
BESSELI | ENGINEERING | Engineering\BesselI::BESSELI
BESSELJ | ENGINEERING | Engineering\BesselJ::BESSELJ
Expand Down
2 changes: 1 addition & 1 deletion docs/references/function-list-by-name.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ AVERAGEIFS | CATEGORY_STATISTICAL | \PhpOffice\PhpSpread

Excel Function | Category | PhpSpreadsheet Function
-------------------------|--------------------------------|--------------------------------------
BAHTTEXT | CATEGORY_TEXT_AND_DATA | **Not yet Implemented**
BAHTTEXT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Thai::getBahtText
BASE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Base::evaluate
BESSELI | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BesselI::BESSELI
BESSELJ | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BesselJ::BESSELJ
Expand Down
2 changes: 1 addition & 1 deletion src/PhpSpreadsheet/Calculation/FunctionArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ class FunctionArray extends CalculationBase
],
'BAHTTEXT' => [
'category' => Category::CATEGORY_TEXT_AND_DATA,
'functionCall' => [Functions::class, 'DUMMY'],
'functionCall' => [TextData\Thai::class, 'getBahtText'],
'argumentCount' => '1',
],
'BASE' => [
Expand Down
139 changes: 139 additions & 0 deletions src/PhpSpreadsheet/Calculation/TextData/Thai.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<?php

namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;

use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;

class Thai
{
use ArrayEnabled;

private const THAI_DIGITS = [
0 => 'ศูนย์',
1 => 'หนึ่ง',
2 => 'สอง',
3 => 'สาม',
4 => 'สี่',
5 => 'ห้า',
6 => 'หก',
7 => 'เจ็ด',
8 => 'แปด',
9 => 'เก้า',
];

private const THAI_UNITS = [
1 => 'สิบ',
2 => 'ร้อย',
3 => 'พัน',
4 => 'หมื่น',
5 => 'แสน',
6 => 'ล้าน',
];

private const THAI_COMPOUND_ONE = 'เอ็ด';
private const THAI_COMPOUND_TWO = 'ยี่';
private const THAI_INTEGER = 'ถ้วน';
private const THAI_MINUS = 'ลบ';
private const THAI_BAHT = 'บาท';
private const THAI_SATANG = 'สตางค์';

/**
* BAHTTEXT.
*
* @param mixed $number The number or array of numbers to convert
*
* @return array<mixed>|string If an array of values is passed as the argument, then the returned result will also be an array with the same dimensions
*/
public static function getBahtText(mixed $number): array|string
{
if (is_array($number)) {
return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $number);
}

if (is_string($number) && preg_match('/^-?\d+$/', $number)) {
$isNegative = str_starts_with($number, '-');
$baht = ltrim($number, '-0') ?: '0';
$satang = '00';
} elseif (is_bool($number) || is_numeric($number)) {
$number += 0;
$isNegative = $number < 0;
[$baht, $satang] = explode('.', number_format(abs($number), 2, '.', ''));
} else {
return ExcelError::VALUE();
}

$hasWhole = $baht !== '0';
$hasFraction = $satang !== '00';

if (!$hasWhole && !$hasFraction) {
return self::THAI_DIGITS[0] . self::THAI_BAHT . self::THAI_INTEGER;
}

$text = $isNegative
? self::THAI_MINUS
: '';

if ($hasWhole) {
$text .= self::convertLarge($baht) . self::THAI_BAHT;
}

$text .= $hasFraction
? self::convertBlock($satang) . self::THAI_SATANG
: self::THAI_INTEGER;

return $text;
}

private static function convertLarge(string $digits): string
{
$length = strlen($digits) % 6 ?: 6;

$chunks = [
substr($digits, 0, $length),
...str_split(substr($digits, $length), 6),
];

$chunks = array_filter($chunks, fn (string $chunk): bool => $chunk !== '');

return implode(
self::THAI_UNITS[6],
array_map(self::convertBlock(...), $chunks)
);
}

private static function convertBlock(string $block): string
{
$out = '';
$length = strlen($block);
$i = 0;

// Hundreds and higher powers
for ($power = $length - 1; $power >= 2; --$power) {
$digit = $block[$i++];
if ($digit !== '0') {
$out .= self::THAI_DIGITS[$digit] . self::THAI_UNITS[$power];
}
}

// Tens
$ten = $length > 1 ? $block[$i++] : '0';
if ($ten !== '0') {
$out .= match ($ten) {
'1' => '',
'2' => self::THAI_COMPOUND_TWO,
default => self::THAI_DIGITS[$ten],
} . self::THAI_UNITS[1];
}

// Ones
$one = $block[$i] ?? '0';
if ($one !== '0') {
$out .= $ten !== '0' && $one === '1'
? self::THAI_COMPOUND_ONE
: self::THAI_DIGITS[$one];
}

return $out;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;

use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PHPUnit\Framework\TestCase;

class BahtTest extends TestCase
{
#[\PHPUnit\Framework\Attributes\DataProvider('providerBAHTTEXT')]
public function testBAHTTEXT(mixed $expectedResult, bool|string|float|int $number): void
{
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();

if (is_bool($number)) {
$formulaValue = $number ? 'TRUE' : 'FALSE';
} elseif (is_string($number)) {
$formulaValue = '"' . $number . '"';
} else {
$formulaValue = (string) $number;
}

$sheet->getCell('A1')->setValue('=BAHTTEXT(' . $formulaValue . ')');
$result = $sheet->getCell('A1')->getCalculatedValue();

self::assertSame($expectedResult, $result);
$spreadsheet->disconnectWorksheets();
}

public static function providerBAHTTEXT(): array
{
return require 'tests/data/Calculation/TextData/BAHTTEXT.php';
}
}
98 changes: 98 additions & 0 deletions tests/data/Calculation/TextData/BAHTTEXT.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

declare(strict_types=1);

return [
[
'ศูนย์บาทถ้วน',
0,
],
[
'หนึ่งบาทถ้วน',
1,
],
[
'สองบาทถ้วน',
2,
],
[
'สิบบาทถ้วน',
10,
],
[
'สิบเอ็ดบาทถ้วน',
11,
],
[
'ยี่สิบเอ็ดบาทถ้วน',
21,
],
[
'สี่สิบสองบาทถ้วน',
42,
],
[
'หนึ่งร้อยบาทถ้วน',
100,
],
[
'หนึ่งพันบาทถ้วน',
1000,
],
[
'หนึ่งพันแปดร้อยแปดสิบเจ็ดบาทถ้วน',
1887,
],
[
'ห้าสิบสตางค์',
0.50,
],
[
'หนึ่งบาทยี่สิบห้าสตางค์',
1.25,
],
[
'หนึ่งร้อยยี่สิบสามบาทสี่สิบห้าสตางค์',
123.45,
],
[
'หนึ่งพันสองร้อยสามสิบสี่บาทห้าสิบหกสตางค์',
1234.56,
],
[
'ลบหนึ่งบาทถ้วน',
-1,
],
[
'ลบสี่สิบสามบาทถ้วน',
-42.999,
],
[
'ลบเก้าสิบเก้าบาทถ้วน',
-99,
],
[
'ลบหนึ่งร้อยยี่สิบสามบาทสี่สิบห้าสตางค์',
-123.45,
],
[
'ลบหนึ่งร้อยยี่สิบสามบาทสี่สิบห้าสตางค์',
'-123.452',
],
[
'เก้าร้อยแปดสิบเจ็ดล้านหกแสนห้าหมื่นสี่พันสามร้อยยี่สิบเอ็ดล้านเก้าแสนแปดหมื่นเจ็ดพันหกร้อยห้าสิบสี่ล้านสามแสนสองหมื่นหนึ่งพันเก้าร้อยแปดสิบเจ็ดล้านหกแสนห้าหมื่นสี่พันสามร้อยยี่สิบเอ็ดบาทถ้วน',
'987654321987654321987654321',
],
[
'หนึ่งบาทถ้วน',
true,
],
[
'ศูนย์บาทถ้วน',
false,
],
[
'#VALUE!',
'ABC',
],
];