使用Lua语言创建DOC/Excel文件时俄文字符显示异常求助
Hey there! Let's tackle that Cyrillic character garbling issue you're running into with Lua. I'll break down solutions for both of your code scenarios below—super common problem when dealing with non-ASCII text, so we'll get it sorted quickly.
1. Fixing Direct DOC File Writing (io.open)
The root issue here is encoding: when you use io.open with "w" mode, it defaults to your system's native encoding, which usually doesn't play nice with Russian characters. To fix this, we need to write the text in UTF-8 with a Byte Order Mark (BOM) so apps like Word recognize the encoding correctly.
Here's the adjusted code:
local fileName = "myfile3.doc" local FileWrite = io.open(fileName, "wb") -- Use binary mode to avoid auto-encoding changes -- Write UTF-8 BOM first to signal the encoding to Word FileWrite:write(string.char(0xEF, 0xBB, 0xBF)) -- Write your Russian text (modern Lua uses UTF-8 strings by default) FileWrite:write("фывф", '\n') FileWrite:close()
Why this works:
"wb"(binary write mode) prevents Lua from modifying the bytes we write, keeping our UTF-8 intact.- The UTF-8 BOM (
0xEFBBBF) tells Word exactly what encoding to use, so it renders Cyrillic characters instead of interpreting them as gibberish.
2. Fixing LuaCOM Excel Character Issues
When using LuaCOM to interact with Excel, the problem is encoding compatibility: Excel expects Cyrillic text in Windows-1251 (the standard Windows Cyrillic encoding), but Lua uses UTF-8 by default. We need to convert our UTF-8 string to the format Excel understands.
Here's the updated Excel code with a conversion helper:
require('luacom') -- Helper function to convert UTF-8 strings to Windows-1251 (Cyrillic) local function utf8_to_win1251(str) local win1251_map = { [0xD081] = 0xA8, [0xD191] = 0xB8, [0xD090] = 0xC0, [0xD091] = 0xC1, [0xD092] = 0xC2, [0xD093] = 0xC3, [0xD094] = 0xC4, [0xD095] = 0xC5, [0xD096] = 0xC6, [0xD097] = 0xC7, [0xD098] = 0xC8, [0xD099] = 0xC9, [0xD09A] = 0xCA, [0xD09B] = 0xCB, [0xD09C] = 0xCC, [0xD09D] = 0xCD, [0xD09E] = 0xCE, [0xD09F] = 0xCF, [0xD0A0] = 0xD0, [0xD0A1] = 0xD1, [0xD0A2] = 0xD2, [0xD0A3] = 0xD3, [0xD0A4] = 0xD4, [0xD0A5] = 0xD5, [0xD0A6] = 0xD6, [0xD0A7] = 0xD7, [0xD0A8] = 0xD8, [0xD0A9] = 0xD9, [0xD0AA] = 0xDA, [0xD0AB] = 0xDB, [0xD0AC] = 0xDC, [0xD0AD] = 0xDD, [0xD0AE] = 0xDE, [0xD0AF] = 0xDF, [0xD0B0] = 0xE0, [0xD0B1] = 0xE1, [0xD0B2] = 0xE2, [0xD0B3] = 0xE3, [0xD0B4] = 0xE4, [0xD0B5] = 0xE5, [0xD0B6] = 0xE6, [0xD0B7] = 0xE7, [0xD0B8] = 0xE8, [0xD0B9] = 0xE9, [0xD0BA] = 0xEA, [0xD0BB] = 0xEB, [0xD0BC] = 0xEC, [0xD0BD] = 0xED, [0xD0BE] = 0xEE, [0xD0BF] = 0xEF, [0xD180] = 0xF0, [0xD181] = 0xF1, [0xD182] = 0xF2, [0xD183] = 0xF3, [0xD184] = 0xF4, [0xD185] = 0xF5, [0xD186] = 0xF6, [0xD187] = 0xF7, [0xD188] = 0xF8, [0xD189] = 0xF9, [0xD18A] = 0xFA, [0xD18B] = 0xFB, [0xD18C] = 0xFC, [0xD18D] = 0xFD, [0xD18E] = 0xFE, [0xD18F] = 0xFF, } local result = {} local i = 1 while i <= #str do local byte1 = str:byte(i) if byte1 < 0x80 then table.insert(result, string.char(byte1)) i = i + 1 elseif byte1 >= 0xD0 and byte1 <= 0xD1 then local byte2 = str:byte(i+1) local key = (byte1 << 8) | byte2 table.insert(result, string.char(win1251_map[key] or '?')) i = i + 2 else table.insert(result, '?') i = i + 1 end end return table.concat(result) end excel = luacom.CreateObject("Excel.Application") excel.Visible = true wb = excel.Workbooks:Add() ws = wb.Worksheets(1) local russian_text = utf8_to_win1251("фывф") for i=1, 10 do ws.Cells(i,1).Value2 = russian_text end
Why this works:
- Excel (on Windows) relies on Windows-1251 for Cyrillic text when interacting via COM. The helper function converts Lua's UTF-8 string to this encoding, so Excel receives the correct byte values for each Russian character.
- This conversion is reliable across most Excel versions, but if you're using a newer build that supports UTF-16, you could also use LuaCOM's wide string support—though Windows-1251 is more compatible for older installations.
内容的提问来源于stack exchange,提问作者one__for__one

