From a890ecbb856484c3249c7345df84677971d6f5c2 Mon Sep 17 00:00:00 2001 From: silence_zhpf Date: Tue, 16 Jul 2024 21:30:27 +0800 Subject: [PATCH 1/2] =?UTF-8?q?chore:=20=E4=BF=AE=E6=94=B9=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=90=8D=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql2doc_core/src/to_markdown.rs | 21 ++++++++++++-- sql2doc_core/src/to_word.rs | 49 +++++++++++++++++++-------------- 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/sql2doc_core/src/to_markdown.rs b/sql2doc_core/src/to_markdown.rs index 782a777..d182d09 100644 --- a/sql2doc_core/src/to_markdown.rs +++ b/sql2doc_core/src/to_markdown.rs @@ -1,7 +1,7 @@ use crate::{ExportAction, Info, SqlConfig}; use std::{ collections::BTreeMap, - fs::File, + fs::OpenOptions, io::{Seek, Write}, path::Path, }; @@ -14,7 +14,12 @@ impl ExportAction for Markdown { ) -> Result { let output = &get_output(config); let path = Path::new(output); - let mut file = File::create(path).unwrap(); + let mut file = OpenOptions::new() + .create(true) + .write(true) + .truncate(true) + .open(path) + .unwrap(); write(groups, &mut file).unwrap(); Ok(output.to_string()) } @@ -70,5 +75,15 @@ where /// 获取输出路径 pub(crate) fn get_output(config: &SqlConfig) -> String { let name = format!("{}.md", config.database); - config.output.as_ref().cloned().unwrap_or(name) + config + .output + .as_ref() + .map(|v| { + if v.ends_with(".md") { + v.to_string() + } else { + format!("{}.md", v) + } + }) + .unwrap_or(name) } diff --git a/sql2doc_core/src/to_word.rs b/sql2doc_core/src/to_word.rs index 0442cc3..c063675 100644 --- a/sql2doc_core/src/to_word.rs +++ b/sql2doc_core/src/to_word.rs @@ -1,22 +1,14 @@ -use crate::ExportAction; -use crate::Info; -use crate::SqlConfig; -use docx_rs::AlignmentType; -use docx_rs::Docx; -use docx_rs::DocxError; -use docx_rs::Paragraph; -use docx_rs::Run; -use docx_rs::Shading; -use docx_rs::Table; -use docx_rs::TableCell; -use docx_rs::TableLayoutType; -use docx_rs::TableRow; -use docx_rs::WidthType; -use std::collections::BTreeMap; -use std::fs::File; -use std::io::Seek; -use std::io::Write; -use std::path::Path; +use crate::{ExportAction, Info, SqlConfig}; +use docx_rs::{ + AlignmentType, Docx, DocxError, Paragraph, Run, Shading, Table, TableCell, TableLayoutType, + TableRow, WidthType, +}; +use std::{ + collections::BTreeMap, + fs::OpenOptions, + io::{Seek, Write}, + path::Path, +}; pub(crate) struct Word {} @@ -27,7 +19,12 @@ impl ExportAction for Word { ) -> Result { let output = &get_output(config); let path = Path::new(output); - let mut file = File::create(path).unwrap(); + let mut file = OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(path) + .unwrap(); write(groups, &mut file).unwrap(); Ok(output.to_string()) } @@ -152,5 +149,15 @@ where /// 获取输出路径 pub(crate) fn get_output(config: &SqlConfig) -> String { let name = format!("{}.docx", config.database); - config.output.as_ref().cloned().unwrap_or(name) + config + .output + .as_ref() + .map(|name| { + if name.ends_with(".docx") { + name.to_string() + } else { + format!("{}.docx", name) + } + }) + .unwrap_or(name) } -- Gitee From 7244d53cd6c079255969526d8494bc9a29779c3b Mon Sep 17 00:00:00 2001 From: silence_zhpf Date: Wed, 17 Jul 2024 10:20:11 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E2=9C=A8=20=E6=B7=BB=E5=8A=A0excel?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✨ cli添加excel导出类型 ✨ ui添加excel导出类型 --- Cargo.lock | 70 +++++++++++++++++++++++++++++++- Cargo.toml | 2 +- cli/Cargo.toml | 2 +- cli/src/main.rs | 2 + sql2doc_core/Cargo.toml | 3 +- sql2doc_core/src/lib.rs | 4 ++ sql2doc_core/src/to_excel/mod.rs | 70 ++++++++++++++++++++++++++++++++ ui/Cargo.toml | 2 +- ui/src/main.rs | 1 + ui/ui/form.slint | 2 +- 10 files changed, 152 insertions(+), 6 deletions(-) create mode 100644 sql2doc_core/src/to_excel/mod.rs diff --git a/Cargo.lock b/Cargo.lock index fea10e3..4ae22b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -226,6 +226,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] + [[package]] name = "arrayref" version = "0.3.7" @@ -1225,6 +1234,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "derive_more" version = "0.99.18" @@ -1298,7 +1318,7 @@ dependencies = [ "serde_json", "thiserror", "xml-rs", - "zip", + "zip 0.6.6", ] [[package]] @@ -2833,6 +2853,12 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "lockfree-object-pool" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" + [[package]] name = "log" version = "0.4.21" @@ -3826,6 +3852,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rust_xlsxwriter" +version = "0.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5183b3255e7f59906fb5630f7b5a3d46c0c27848ca947312011ac03b496f26b" +dependencies = [ + "regex", + "zip 2.1.3", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -4342,6 +4378,7 @@ name = "sql2doc_core" version = "0.2.4" dependencies = [ "docx-rs", + "rust_xlsxwriter", "serde", "sqlx", "thiserror", @@ -6166,6 +6203,37 @@ dependencies = [ "flate2", ] +[[package]] +name = "zip" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "775a2b471036342aa69bc5a602bc889cb0a06cda00477d0c69566757d5553d39" +dependencies = [ + "arbitrary", + "crc32fast", + "crossbeam-utils", + "displaydoc", + "flate2", + "indexmap", + "memchr", + "thiserror", + "zopfli", +] + +[[package]] +name = "zopfli" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" +dependencies = [ + "bumpalo", + "crc32fast", + "lockfree-object-pool", + "log", + "once_cell", + "simd-adler32", +] + [[package]] name = "zune-inflate" version = "0.2.54" diff --git a/Cargo.toml b/Cargo.toml index 3a64dff..db802b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "sql2doc" -version = "0.2.4" +version = "0.2.5" edition = "2021" publish = ["crates-io"] diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 81a3663..f2136ec 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "s2d" -version = "0.2.4" +version = "0.2.5" edition = "2021" [dependencies] diff --git a/cli/src/main.rs b/cli/src/main.rs index 71f7471..8b3ac31 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -28,6 +28,7 @@ enum ExportEnum { Docx, Markdown, Html, + Excel, } #[derive(Debug, Clone, Copy, ValueEnum, Default)] @@ -52,6 +53,7 @@ impl From for ExportType { ExportEnum::Docx => Self::Docx, ExportEnum::Markdown => Self::Markdown, ExportEnum::Html => Self::Html, + ExportEnum::Excel => Self::Excel, } } } diff --git a/sql2doc_core/Cargo.toml b/sql2doc_core/Cargo.toml index 94b9b58..6570f6f 100644 --- a/sql2doc_core/Cargo.toml +++ b/sql2doc_core/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "sql2doc_core" -version = "0.2.4" +version = "0.2.5" edition = "2021" [dependencies] # docx-rs = "0.4.17" docx-rs = { git = "https://github.com/hackers267/docx-rs.git", branch = "main" } +rust_xlsxwriter = "0.70.0" serde = { version = "1.0.203", features = ["derive"] } sqlx = { version = "0.7.4", features = ["mysql", "runtime-tokio"] } thiserror = "1.0.61" diff --git a/sql2doc_core/src/lib.rs b/sql2doc_core/src/lib.rs index a741eb0..d553e23 100644 --- a/sql2doc_core/src/lib.rs +++ b/sql2doc_core/src/lib.rs @@ -5,6 +5,7 @@ use std::{ io::{Seek, Write}, }; use thiserror::Error; +use to_excel::Excel; use to_html::Html; use to_markdown::Markdown; use to_word::{write, Word}; @@ -12,6 +13,7 @@ use to_word::{write, Word}; mod config; mod mssql; mod mysql; +mod to_excel; mod to_html; mod to_markdown; mod to_word; @@ -49,6 +51,7 @@ pub enum ExportType { Docx, Markdown, Html, + Excel, } /// 根据不同的SQL类型,异步执行数据库查询并生成结果文件。 @@ -75,6 +78,7 @@ pub async fn run( ExportType::Docx => Word::run(config, &groups), ExportType::Markdown => Markdown::run(config, &groups), ExportType::Html => Html::run(config, &groups), + ExportType::Excel => Excel::run(config, &groups), } } diff --git a/sql2doc_core/src/to_excel/mod.rs b/sql2doc_core/src/to_excel/mod.rs new file mode 100644 index 0000000..2ddbe03 --- /dev/null +++ b/sql2doc_core/src/to_excel/mod.rs @@ -0,0 +1,70 @@ +use rust_xlsxwriter::{Format, Workbook}; + +use crate::{ExportAction, Info, SqlConfig}; + +pub(crate) struct Excel {} + +impl ExportAction for Excel { + fn run( + config: &crate::SqlConfig, + groups: &std::collections::BTreeMap<&String, Vec<&crate::Info>>, + ) -> Result { + let name = get_output(config); + let mut workbook = Workbook::new(); + let bold_format = Format::new().set_bold(); + groups.iter().for_each(|(name, list)| { + let worksheet = workbook.add_worksheet(); + worksheet.set_name(*name).unwrap(); + worksheet + .write_with_format(0, 0, "序号", &bold_format) + .unwrap(); + worksheet + .write_with_format(0, 1, "列名", &bold_format) + .unwrap(); + worksheet + .write_with_format(0, 2, "数据类型", &bold_format) + .unwrap(); + worksheet + .write_with_format(0, 3, "为Null", &bold_format) + .unwrap(); + worksheet + .write_with_format(0, 4, "备注", &bold_format) + .unwrap(); + list.iter().enumerate().for_each(|(index, info)| { + let Info { + ordinal_position, + data_type, + is_nullable, + column_name, + column_comment, + .. + } = info; + let column_comment = column_comment.as_ref().map_or("", |v| v.as_str()); + let index = index + 1; + worksheet.write(index as u32, 0, *ordinal_position).unwrap(); + worksheet.write(index as u32, 1, column_name).unwrap(); + worksheet.write(index as u32, 2, data_type).unwrap(); + worksheet.write(index as u32, 3, is_nullable).unwrap(); + worksheet.write(index as u32, 4, column_comment).unwrap(); + }); + }); + workbook.save(&name).unwrap(); + Ok(name) + } +} + +fn get_output(config: &SqlConfig) -> String { + let name = config.database.as_str().to_string(); + let name = format!("{name}.xlsx"); + config + .output + .as_ref() + .map(|v| { + if v.ends_with(".xlsx") { + v.to_string() + } else { + format!("{}.xlsx", v) + } + }) + .unwrap_or(name) +} diff --git a/ui/Cargo.toml b/ui/Cargo.toml index 4a8acd7..e6f5b10 100644 --- a/ui/Cargo.toml +++ b/ui/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ui" -version = "0.2.4" +version = "0.2.5" edition = "2021" build = "build.rs" diff --git a/ui/src/main.rs b/ui/src/main.rs index 6eb6228..e9152e9 100644 --- a/ui/src/main.rs +++ b/ui/src/main.rs @@ -29,6 +29,7 @@ fn main() { "word" => ExportType::Docx, "markdown" => ExportType::Markdown, "html" => ExportType::Html, + "excel" => ExportType::Excel, _ => ExportType::Docx, }; let _ = spawn_local(async move { diff --git a/ui/ui/form.slint b/ui/ui/form.slint index e32de81..73c6aa4 100644 --- a/ui/ui/form.slint +++ b/ui/ui/form.slint @@ -61,7 +61,7 @@ export component Form { ex := SelectItem { label: "导出:"; value: export; - model: ["Word", "Markdown", "HTML"]; + model: ["Word", "Markdown", "HTML", "Excel"]; } Button { -- Gitee