Skip to content

Commit

Permalink
feta:
Browse files Browse the repository at this point in the history
- add subcli xlsx2csv and csv2xlsx
- add categories and authors field in Cargo.toml
  • Loading branch information
sharkLoc committed Apr 24, 2024
1 parent 53f8fcc commit 8432608
Show file tree
Hide file tree
Showing 13 changed files with 278 additions and 42 deletions.
88 changes: 87 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
[package]
name = "xtab"
version = "0.0.2"
version = "0.0.3"
authors = ["sharkLoc <[email protected]>"]
edition = "2021"
homepage = "https://github.com/sharkLoc/xtab"
description = "xtab: CSV command line utilities"
repository = "https://github.com/sharkLoc/xtab"
keywords = ["csv"]
keywords = ["csv","tsv"]
categories = ["command-line-utilities"]
readme = "README.md"
license = "MIT"

Expand All @@ -15,11 +17,13 @@ license = "MIT"
anyhow = "1.0.82"
atty = "0.2.14"
bzip2 = "0.4.4"
calamine = "0.24.0"
chrono = "0.4.38"
clap = { version = "4.5.4", features = ["derive", "wrap_help"] }
comfy-table = "7.1.1"
csv = "1.3.0"
env_logger = "0.10.0"
flate2 = "1.0.28"
log = "0.4.21"
rust_xlsxwriter = "0.64.2"
xz2 = "0.1.7"
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ cargo b --release

```bash
xtab -- CSV command line utilities
Version: 0.0.2
Version: 0.0.3

Authors: sharkLoc <[email protected]>
Source code: https://github.com/sharkLoc/xtab.git
Expand All @@ -40,13 +40,15 @@ Usage: xtab [OPTIONS] [CSV] <COMMAND>

Commands:
addheader Set new header for CSV file [aliases: ah]
csv2xlsx Convert CSV/TSV files to XLSX file [aliases: c2x]
dim Dimensions of CSV file
drop Drop or Select CSV fields by columns index
freq freq
head Print first N records from CSV file
pretty Convert CSV to a readable aligned table
tail Print last N records from CSV file
uniq Unique data with keys
xlsx2csv Convert XLSX to CSV format [aliases: x2c]
view Show CSV file content
help Print this message or the help of the given subcommand(s)

Expand Down
Binary file added example/CRA007254.xlsx
Binary file not shown.
37 changes: 32 additions & 5 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@ use clap::{value_parser, Parser};
#[command(
name = "xtab",
author = "sharkLoc",
version = "0.0.2",
version = "0.0.3",
next_line_help = false,
about = "CSV command line utilities"
about = "CSV command line utilities",
long_about = "A simple and cross-platform program for CSV file manipulation"
)]
#[command(propagate_version = false, disable_help_flag = false, disable_version_flag = true)]
#[command(long_about = "A simple and cross-platform program for CSV file manipulation")]
#[command(before_help=r"xtab supports reading and writing gzip/bzip2/xz format file.
Compression level:
format range default crate
gzip 1-9 6 https://crates.io/crates/flate2
bzip2 1-9 6 https://crates.io/crates/bzip2
xz 1-9 6 https://crates.io/crates/xz2"
)]
#[command(help_template = "{name} -- {about}\nVersion: {version}\
\n\nAuthors: {author} <[email protected]>\
#[command(help_template = "{name} -- {about}\n\nVersion: {version}\
\nAuthors: {author} <[email protected]>\
\nSource code: https://github.com/sharkLoc/xtab.git\
\n\n{before-help}
{usage-heading} {usage}\n\n{all-args}\n\nUse \"xtab help [command]\" for more information about a command")]
Expand Down Expand Up @@ -78,6 +78,19 @@ pub enum Cmd {
output: Option<PathBuf>,
},

/// Convert CSV/TSV files to XLSX file
#[command(visible_alias = "c2x")]
csv2xlsx {
/// If set, bold first line in XLSX file
#[arg(short = 'B', long = "bold-first", help_heading = Some("FLAGS"))]
bold: bool,
/// If set, border first line in XLSX file
#[arg(short = 'b', long = "border-first", help_heading = Some("FLAGS"))]
border: bool,
/// Output xlsx file name, e.g, result.xlsx
#[arg(short = 'x', long = "xlsx", value_name = "FILE", default_value_t = String::from("Sheet1.xlsx"))]
xlsx: String,
},
/// Dimensions of CSV file
dim {
/// Output file name, file ending in .gz/.bz2/.xz will be compressed automatically, if file not specified write data to stdout
Expand Down Expand Up @@ -166,6 +179,20 @@ pub enum Cmd {
output: Option<PathBuf>,
},

/// Convert XLSX to CSV format
#[command(visible_alias = "x2c")]
xlsx2csv {
/// Input XLSX file
#[arg(value_name = "FILE")]
xlsx: Option<PathBuf>,
/// Select Nth sheet to retrieve
#[arg(short = 'i', long = "sheet-index", value_name = "INT", default_value_t=1)]
idx: usize,
/// Output file name, file ending in .gz/.bz2/.xz will be compressed automatically, if file not specified write data to stdout
#[arg(short = 'o', long = "out-csv", value_name = "FILE")]
csv: Option<PathBuf>,
},

/// Show CSV file content
view {
/// Skip first N records, not include the header row when option "--no-header" enabled. eg "-s 10 --no-header" will skip 11 records
Expand Down
52 changes: 52 additions & 0 deletions src/command/csv2xlsx.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use crate::utils::*;
use anyhow::{Error, Ok};
use csv::ReaderBuilder;
use log::info;
use rust_xlsxwriter::{Format, FormatBorder, Workbook};
use std::{path::PathBuf, time::Instant};

pub fn csv_xlsx(
no_header: bool,
delimiter: u8,
bold_first: bool,
border_first: bool,
csv: Option<PathBuf>,
xlsx: &str,
) -> Result<(), Error> {
let start = Instant::now();

let mut csv_reader = ReaderBuilder::new()
.has_headers(no_header)
.flexible(true)
.delimiter(delimiter)
.from_reader(file_reader(csv.as_ref())?);

match csv {
Some(csv) => info!("read file from: {:?}", csv),
None => info!("read file from stdin "),
}

let mut work_book = Workbook::new();
let work_sheet = work_book.add_worksheet();

let format = match (bold_first, border_first) {
(true, true) => Format::new().set_bold().set_border(FormatBorder::Double),
(false, false) => Format::new(),
(true, false) => Format::new().set_bold(),
(false, true) => Format::new().set_border(FormatBorder::Double),
};

for (nrow, rec) in csv_reader.records().flatten().enumerate() {
for (ncol, cell) in rec.iter().enumerate() {
if (bold_first || border_first) && nrow == 0 {
work_sheet.write_with_format(nrow as u32, ncol as u16, cell, &format)?;
} else {
work_sheet.write(nrow as u32, ncol as u16, cell)?;
}
}
}
work_book.save(xlsx)?;

info!("time elapsed is: {:?}", start.elapsed());
Ok(())
}
8 changes: 4 additions & 4 deletions src/command/drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub fn drop_csv(
for idx in index_str.split(',').collect::<Vec<&str>>() {
let idx = idx.parse::<usize>()?;
if col_index.contains(&idx) {
warn!("duplicate columns index {}, keep first one",idx);
warn!("duplicate columns index {}, keep first one", idx);
continue;
} else {
col_index.push(idx);
Expand All @@ -49,13 +49,13 @@ pub fn drop_csv(

for rec in csv_reader.records().flatten() {
let mut rec_new = StringRecord::new();
for (idx,each) in rec.iter().enumerate() {
for (idx, each) in rec.iter().enumerate() {
if invert {
if col_index.contains(&(idx+1)) {
if col_index.contains(&(idx + 1)) {
rec_new.push_field(each);
}
} else {
if !col_index.contains(&(idx+1)) {
if !col_index.contains(&(idx + 1)) {
rec_new.push_field(each);
}
}
Expand Down
Loading

0 comments on commit 8432608

Please sign in to comment.