Skip to content

Commit 1e40387

Browse files
authored
Merge pull request #4715 from RobinvanderVliet/add-bahttext-function
Implement missing `BAHTTEXT` function
2 parents 467eada + 5765770 commit 1e40387

File tree

8 files changed

+279
-4
lines changed

8 files changed

+279
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org). Thia is a
1111

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

1516
### Removed
1617

docs/references/function-list-by-category.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ Excel Function | PhpSpreadsheet Function
525525
-------------------------|--------------------------------------
526526
ARRAYTOTEXT | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Text::fromArray
527527
ASC | **Not yet Implemented**
528-
BAHTTEXT | **Not yet Implemented**
528+
BAHTTEXT | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Thai::getBahtText
529529
CHAR | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CharacterConvert::character
530530
CLEAN | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Trim::nonPrintable
531531
CODE | \PhpOffice\PhpSpreadsheet\Calculation\TextData\CharacterConvert::code

docs/references/function-list-by-name-compact.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ AVERAGEIFS | STATISTICAL | Statistical\Conditional::AVER
4343

4444
Excel Function | Category | PhpSpreadsheet Function
4545
-------------------------|-----------------------|--------------------------------------
46-
BAHTTEXT | TEXT_AND_DATA | **Not yet Implemented**
46+
BAHTTEXT | TEXT_AND_DATA | TextData\Thai::getBahtText
4747
BASE | MATH_AND_TRIG | MathTrig\Base::evaluate
4848
BESSELI | ENGINEERING | Engineering\BesselI::BESSELI
4949
BESSELJ | ENGINEERING | Engineering\BesselJ::BESSELJ

docs/references/function-list-by-name.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ AVERAGEIFS | CATEGORY_STATISTICAL | \PhpOffice\PhpSpread
3939

4040
Excel Function | Category | PhpSpreadsheet Function
4141
-------------------------|--------------------------------|--------------------------------------
42-
BAHTTEXT | CATEGORY_TEXT_AND_DATA | **Not yet Implemented**
42+
BAHTTEXT | CATEGORY_TEXT_AND_DATA | \PhpOffice\PhpSpreadsheet\Calculation\TextData\Thai::getBahtText
4343
BASE | CATEGORY_MATH_AND_TRIG | \PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Base::evaluate
4444
BESSELI | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BesselI::BESSELI
4545
BESSELJ | CATEGORY_ENGINEERING | \PhpOffice\PhpSpreadsheet\Calculation\Engineering\BesselJ::BESSELJ

src/PhpSpreadsheet/Calculation/FunctionArray.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ class FunctionArray extends CalculationBase
149149
],
150150
'BAHTTEXT' => [
151151
'category' => Category::CATEGORY_TEXT_AND_DATA,
152-
'functionCall' => [Functions::class, 'DUMMY'],
152+
'functionCall' => [TextData\Thai::class, 'getBahtText'],
153153
'argumentCount' => '1',
154154
],
155155
'BASE' => [
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<?php
2+
3+
namespace PhpOffice\PhpSpreadsheet\Calculation\TextData;
4+
5+
use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
6+
use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
7+
8+
class Thai
9+
{
10+
use ArrayEnabled;
11+
12+
private const THAI_DIGITS = [
13+
0 => 'ศูนย์',
14+
1 => 'หนึ่ง',
15+
2 => 'สอง',
16+
3 => 'สาม',
17+
4 => 'สี่',
18+
5 => 'ห้า',
19+
6 => 'หก',
20+
7 => 'เจ็ด',
21+
8 => 'แปด',
22+
9 => 'เก้า',
23+
];
24+
25+
private const THAI_UNITS = [
26+
1 => 'สิบ',
27+
2 => 'ร้อย',
28+
3 => 'พัน',
29+
4 => 'หมื่น',
30+
5 => 'แสน',
31+
6 => 'ล้าน',
32+
];
33+
34+
private const THAI_COMPOUND_ONE = 'เอ็ด';
35+
private const THAI_COMPOUND_TWO = 'ยี่';
36+
private const THAI_INTEGER = 'ถ้วน';
37+
private const THAI_MINUS = 'ลบ';
38+
private const THAI_BAHT = 'บาท';
39+
private const THAI_SATANG = 'สตางค์';
40+
41+
/**
42+
* BAHTTEXT.
43+
*
44+
* @param mixed $number The number or array of numbers to convert
45+
*
46+
* @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
47+
*/
48+
public static function getBahtText(mixed $number): array|string
49+
{
50+
if (is_array($number)) {
51+
return self::evaluateSingleArgumentArray([self::class, __FUNCTION__], $number);
52+
}
53+
54+
if (is_string($number) && preg_match('/^-?\d+$/', $number)) {
55+
$isNegative = str_starts_with($number, '-');
56+
$baht = ltrim($number, '-0') ?: '0';
57+
$satang = '00';
58+
} elseif (is_bool($number) || is_numeric($number)) {
59+
$number += 0;
60+
$isNegative = $number < 0;
61+
[$baht, $satang] = explode('.', number_format(abs($number), 2, '.', ''));
62+
} else {
63+
return ExcelError::VALUE();
64+
}
65+
66+
$hasWhole = $baht !== '0';
67+
$hasFraction = $satang !== '00';
68+
69+
if (!$hasWhole && !$hasFraction) {
70+
return self::THAI_DIGITS[0] . self::THAI_BAHT . self::THAI_INTEGER;
71+
}
72+
73+
$text = $isNegative
74+
? self::THAI_MINUS
75+
: '';
76+
77+
if ($hasWhole) {
78+
$text .= self::convertLarge($baht) . self::THAI_BAHT;
79+
}
80+
81+
$text .= $hasFraction
82+
? self::convertBlock($satang) . self::THAI_SATANG
83+
: self::THAI_INTEGER;
84+
85+
return $text;
86+
}
87+
88+
private static function convertLarge(string $digits): string
89+
{
90+
$length = strlen($digits) % 6 ?: 6;
91+
92+
$chunks = [
93+
substr($digits, 0, $length),
94+
...str_split(substr($digits, $length), 6),
95+
];
96+
97+
$chunks = array_filter($chunks, fn (string $chunk): bool => $chunk !== '');
98+
99+
return implode(
100+
self::THAI_UNITS[6],
101+
array_map(self::convertBlock(...), $chunks)
102+
);
103+
}
104+
105+
private static function convertBlock(string $block): string
106+
{
107+
$out = '';
108+
$length = strlen($block);
109+
$i = 0;
110+
111+
// Hundreds and higher powers
112+
for ($power = $length - 1; $power >= 2; --$power) {
113+
$digit = $block[$i++];
114+
if ($digit !== '0') {
115+
$out .= self::THAI_DIGITS[$digit] . self::THAI_UNITS[$power];
116+
}
117+
}
118+
119+
// Tens
120+
$ten = $length > 1 ? $block[$i++] : '0';
121+
if ($ten !== '0') {
122+
$out .= match ($ten) {
123+
'1' => '',
124+
'2' => self::THAI_COMPOUND_TWO,
125+
default => self::THAI_DIGITS[$ten],
126+
} . self::THAI_UNITS[1];
127+
}
128+
129+
// Ones
130+
$one = $block[$i] ?? '0';
131+
if ($one !== '0') {
132+
$out .= $ten !== '0' && $one === '1'
133+
? self::THAI_COMPOUND_ONE
134+
: self::THAI_DIGITS[$one];
135+
}
136+
137+
return $out;
138+
}
139+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\TextData;
6+
7+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
8+
use PHPUnit\Framework\TestCase;
9+
10+
class BahtTest extends TestCase
11+
{
12+
#[\PHPUnit\Framework\Attributes\DataProvider('providerBAHTTEXT')]
13+
public function testBAHTTEXT(mixed $expectedResult, bool|string|float|int $number): void
14+
{
15+
$spreadsheet = new Spreadsheet();
16+
$sheet = $spreadsheet->getActiveSheet();
17+
18+
if (is_bool($number)) {
19+
$formulaValue = $number ? 'TRUE' : 'FALSE';
20+
} elseif (is_string($number)) {
21+
$formulaValue = '"' . $number . '"';
22+
} else {
23+
$formulaValue = (string) $number;
24+
}
25+
26+
$sheet->getCell('A1')->setValue('=BAHTTEXT(' . $formulaValue . ')');
27+
$result = $sheet->getCell('A1')->getCalculatedValue();
28+
29+
self::assertSame($expectedResult, $result);
30+
$spreadsheet->disconnectWorksheets();
31+
}
32+
33+
public static function providerBAHTTEXT(): array
34+
{
35+
return require 'tests/data/Calculation/TextData/BAHTTEXT.php';
36+
}
37+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
return [
6+
[
7+
'ศูนย์บาทถ้วน',
8+
0,
9+
],
10+
[
11+
'หนึ่งบาทถ้วน',
12+
1,
13+
],
14+
[
15+
'สองบาทถ้วน',
16+
2,
17+
],
18+
[
19+
'สิบบาทถ้วน',
20+
10,
21+
],
22+
[
23+
'สิบเอ็ดบาทถ้วน',
24+
11,
25+
],
26+
[
27+
'ยี่สิบเอ็ดบาทถ้วน',
28+
21,
29+
],
30+
[
31+
'สี่สิบสองบาทถ้วน',
32+
42,
33+
],
34+
[
35+
'หนึ่งร้อยบาทถ้วน',
36+
100,
37+
],
38+
[
39+
'หนึ่งพันบาทถ้วน',
40+
1000,
41+
],
42+
[
43+
'หนึ่งพันแปดร้อยแปดสิบเจ็ดบาทถ้วน',
44+
1887,
45+
],
46+
[
47+
'ห้าสิบสตางค์',
48+
0.50,
49+
],
50+
[
51+
'หนึ่งบาทยี่สิบห้าสตางค์',
52+
1.25,
53+
],
54+
[
55+
'หนึ่งร้อยยี่สิบสามบาทสี่สิบห้าสตางค์',
56+
123.45,
57+
],
58+
[
59+
'หนึ่งพันสองร้อยสามสิบสี่บาทห้าสิบหกสตางค์',
60+
1234.56,
61+
],
62+
[
63+
'ลบหนึ่งบาทถ้วน',
64+
-1,
65+
],
66+
[
67+
'ลบสี่สิบสามบาทถ้วน',
68+
-42.999,
69+
],
70+
[
71+
'ลบเก้าสิบเก้าบาทถ้วน',
72+
-99,
73+
],
74+
[
75+
'ลบหนึ่งร้อยยี่สิบสามบาทสี่สิบห้าสตางค์',
76+
-123.45,
77+
],
78+
[
79+
'ลบหนึ่งร้อยยี่สิบสามบาทสี่สิบห้าสตางค์',
80+
'-123.452',
81+
],
82+
[
83+
'เก้าร้อยแปดสิบเจ็ดล้านหกแสนห้าหมื่นสี่พันสามร้อยยี่สิบเอ็ดล้านเก้าแสนแปดหมื่นเจ็ดพันหกร้อยห้าสิบสี่ล้านสามแสนสองหมื่นหนึ่งพันเก้าร้อยแปดสิบเจ็ดล้านหกแสนห้าหมื่นสี่พันสามร้อยยี่สิบเอ็ดบาทถ้วน',
84+
'987654321987654321987654321',
85+
],
86+
[
87+
'หนึ่งบาทถ้วน',
88+
true,
89+
],
90+
[
91+
'ศูนย์บาทถ้วน',
92+
false,
93+
],
94+
[
95+
'#VALUE!',
96+
'ABC',
97+
],
98+
];

0 commit comments

Comments
 (0)