diff --git a/dexcel/src/main.rs b/dexcel/src/main.rs index 0a1139f..065a046 100644 --- a/dexcel/src/main.rs +++ b/dexcel/src/main.rs @@ -411,7 +411,7 @@ fn count_excel(book: &Spreadsheet, sheet_name: &Option) -> Result<()> { Ok(()) } -// --- 修改版:插入行 (支持日期写入) --- +// --- 最终版:插入行 (支持所有换行格式 + 自动换行 + 样式保留) --- fn insert_excel( book: &mut Spreadsheet, value: &str, @@ -438,7 +438,7 @@ fn insert_excel( sheet.insert_new_row(&insert_idx_1based, &1); } - // 写入数据 (逻辑增强) + // 写入数据 let vals: Vec<&str> = value.split(split).collect(); for (i, val) in vals.iter().enumerate() { let col = (i + 1) as u32; @@ -446,15 +446,40 @@ fn insert_excel( let val_trimmed = val.trim(); if !val_trimmed.is_empty() { - // 1. 尝试解析日期 + // 1. 统一换行格式:处理所有换行符为 Excel 标准的 \n + // 同时保留对 Shell 转义的兼容(即使 Shell 吃掉了也能工作) + let processed_val = val_trimmed + .replace("\r\n", "\n") // 真正的 Windows 换行 (ASCII 13+10) -> Unix 换行 + .replace("\\r\\n", "\n") // 字面量 \r\n (4个字符) -> Unix 换行 + .replace("\\n", "\n") // 字面量 \n (2个字符) -> Unix 换行 + .replace("\\t", "\t"); // 字面量 \t (2个字符) -> 制表符 + + // 2. 尝试解析日期(用原始 trim 后的值,日期不应该包含换行) if let Some((dt, excel_fmt)) = try_parse_datetime(val_trimmed) { let serial = datetime_to_excel_serial(&dt); cell.set_value_number(serial); - // 关键:设置单元格格式,这样 Excel 才会把它当日期看 cell.get_style_mut().get_number_format_mut().set_format_code(excel_fmt); } else { - // 2. 写入文本 - cell.set_value(val_trimmed); + // 3. 写入处理后的纯文本 + cell.set_value(processed_val.clone()); + } + + // 4. 【关键】统一判断:只要内容包含换行符,就强制开启自动换行 + 自动调整行高 + // 不管是日期还是文本(虽然日期带换行极少见,但逻辑完整) + if processed_val.contains('\n') { + // 保留单元格原有的所有对齐样式,只开启自动换行 + let mut align = cell.get_style().get_alignment().cloned().unwrap_or_default(); + align.set_wrap_text(true); + cell.get_style_mut().set_alignment(align); + + // 5. 自动调整行高(简单估算) + let line_count = processed_val.matches('\n').count() + 1; + let estimated_height = (line_count as f64) * 15.0; // 每行约 15 磅 + let row_dim = sheet.get_row_dimension_mut(&insert_idx_1based); + // 只有当当前行高小于估算值时才调整,避免覆盖用户已设置的行高 + if *row_dim.get_height() < estimated_height { + row_dim.set_height(estimated_height); + } } } } @@ -463,7 +488,7 @@ fn insert_excel( Ok(()) } -// --- 修改版:更新行 (支持日期写入) --- +// --- 最终版:更新行 (支持所有换行格式 + 自动换行 + 样式保留) --- fn update_excel( book: &mut Spreadsheet, value: &str, @@ -486,14 +511,37 @@ fn update_excel( let val_trimmed = val.trim(); if !val_trimmed.is_empty() { - // 1. 尝试解析日期 + // 1. 统一换行格式 + let processed_val = val_trimmed + .replace("\r\n", "\n") // 真正的 Windows 换行 (ASCII 13+10) -> Unix 换行 + .replace("\\r\\n", "\n") // 字面量 \r\n (4个字符) -> Unix 换行 + .replace("\\n", "\n") // 字面量 \n (2个字符) -> Unix 换行 + .replace("\\t", "\t"); // 字面量 \t (2个字符) -> 制表符 + + // 2. 尝试解析日期 if let Some((dt, excel_fmt)) = try_parse_datetime(val_trimmed) { let serial = datetime_to_excel_serial(&dt); cell_obj.set_value_number(serial); cell_obj.get_style_mut().get_number_format_mut().set_format_code(excel_fmt); } else { - // 2. 写入文本 - cell_obj.set_value(val_trimmed); + // 3. 写入文本 + cell_obj.set_value(processed_val.clone()); + } + + // 4. 统一开启自动换行 + 自动调整行高 + if processed_val.contains('\n') { + let mut align = cell_obj.get_style().get_alignment().cloned().unwrap_or_default(); + align.set_wrap_text(true); + cell_obj.get_style_mut().set_alignment(align); + + // 5. 自动调整行高(简单估算) + let line_count = processed_val.matches('\n').count() + 1; + let estimated_height = (line_count as f64) * 15.0; // 每行约 15 磅 + let row_dim = sheet.get_row_dimension_mut(&target_row); + // 只有当当前行高小于估算值时才调整,避免覆盖用户已设置的行高 + if *row_dim.get_height() < estimated_height { + row_dim.set_height(estimated_height); + } } } }