自定义函数 JSA_A_UINT8ARRAYTOUTF16TOSTRING 将UTF-16解码为字符
function JSA_A_UINT8ARRAYTOUTF16TOSTRING(uint8Array, format, endianness, hasBom) {
//表格中使用函数,参数留空时,默认值处理
uint8Array = uint8Array === -2147352572 ? undefined : uint8Array;
format = format === -2147352572 ? undefined : format;
endianness = endianness === -2147352572 ? undefined : endianness;
hasBom = hasBom === -2147352572 ? undefined : hasBom;
// 参数验证和默认值处理
uint8Array = (Array.isArray(uint8Array.valueOf()) || (uint8Array instanceof Uint8Array)) ? Array.from(uint8Array.valueOf()).flat(Infinity).filter(v => v !== null && v !== undefined && v !== "") : [uint8Array.valueOf()].filter(v => v !== null && v !== undefined && v !== "");
format = (format || 'dec').toLowerCase();
endianness = (endianness || 'BE').toUpperCase();
hasBom = hasBom || false;
// 验证参数有效性
if (uint8Array.length === 0) {
return "#N/A";
}
if (!['bin', 'hex', 'dec'].includes(format)) {
return "#N/A";
}
if (!['BE', 'LE'].includes(endianness)) {
return "#N/A";
}
const processInput = (data, format) => { // 处理输入格式,转为十进制数组
switch (format.toLowerCase()) {
case 'bin':
return data.map(x => parseInt(x, 2));
case 'hex':
return data.map(x => parseInt(x, 16));
case 'dec':
return Array.isArray(data[0]) ? data.flat() : data;
default:
return "#N/A";
}
};
const checkAndRemoveBom = (data, endianness, hasBomFlag) => { // 检查并移除BOM
const bom = endianness.toUpperCase() === 'BE' ? [254, 255] : [255, 254];
if (hasBomFlag && data.length >= 2 && data[0] === bom[0] && data[1] === bom[1]) {
return data.slice(2);
}
return data;
};
const bytesToWords = (bytes, endianness) => { // 将字节转换为16位字
if (bytes.length % 2 !== 0) {
return "#N/A";
}
const words = [];
const endian = endianness.toUpperCase();
for (let i = 0; i < bytes.length; i += 2) {
let word;
if (endian === 'BE') {
word = (bytes[i] << 8) | bytes[i + 1];
} else { // LE
word = (bytes[i + 1] << 8) | bytes[i];
}
words.push(word);
}
return words; //二进制为16位的数字组成的数组
};
const decodeWords = (words) => { // 解码16位字为字符串
let result = '';
for (let i = 0; i < words.length; i++) {
const currentWord = words[i];
const prevWord = i > 0 ? words[i - 1] : 0;
const nextWord = i < (words.length - 1) ? words[i + 1] : 0;
const isHighSurrogate = currentWord >= 55296 && currentWord <= 56319;
const isLowSurrogate = currentWord >= 56320 && currentWord <= 57343;
const hasValidPair = isHighSurrogate && i < words.length - 1 && nextWord >= 56320 && nextWord <= 57343;
let char;
if (hasValidPair) { // 处理代理对
const high_10 = currentWord & 1023;
const low_10 = nextWord & 1023;
const codePoint = ((high_10 << 10) | low_10) + 65536;
char = String.fromCodePoint(codePoint);
i++; // 跳过下一个字,因为已经处理了
} else if (isLowSurrogate && i > 0 && prevWord >= 55296 && prevWord <= 56319) { // 如果是低代理且前一个是高代理,说明已经在上一次迭代中处理过了
char = '';
} else { // 直接转换基本多文种平面字符
char = String.fromCharCode(currentWord);
}
result += char;
}
return result;
};
try {
const processedData = processInput(uint8Array, format); // 处理输入数据,转为十进制数组
const dataWithoutBom = checkAndRemoveBom(processedData, endianness, hasBom); // 检查并移除BOM
const validData = dataWithoutBom.length % 2 === 0 ? dataWithoutBom : dataWithoutBom.slice(0, -1); // 确保数据长度为偶数
const words = bytesToWords(validData, endianness); // 将字节转换为16位字
return decodeWords(words); // 解码为字符串
} catch(error) {
return "#N/A";
}
}插入函数对话框、函数参数对话框:
加载宏文件function Workbook_Open(){}中添加以下代码。
Application.MacroOptions("JSA_A_UINT8ARRAYTOUTF16TOSTRING", "将UTF-16编码的Uint8Array解码为字符串。", undefined, undefined, undefined, undefined, 14, undefined, undefined, undefined, ['UTF-16编码的Uint8Array,也可以是单行或多行数组。', '输入字节的格式。"dec":十进制字节值(默认),"hex":十六进制字节值,"bin":二进制字节值。', '字节序,"utf-16"需指定。"BE":大端序(高位字节在前)(默认),"LE":小端序(低位字节在前)。', '是否包含字节序标记(BOM),"utf-16"需指定。TRUE:包含,FALSE:不包含(默认)。']);