Skip to content

Commit

Permalink
Merge pull request #2 from CHRISCARLON/nebby-dev-branch
Browse files Browse the repository at this point in the history
Nebby dev branch
  • Loading branch information
CHRISCARLON authored Sep 17, 2024
2 parents 5152a77 + 356368c commit 88f393b
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 156 deletions.
10 changes: 6 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
[package]
name = "exqs"
name = "Nebby"
version = "0.1.0"
edition = "2021"

[[bin]]
name = "exqs"
name = "nebb"
path = "src/main.rs"

[dependencies]
calamine = "0.25.0"
comfy-table = "7.1.0"
clap = { version = "4.5.7", features = ["derive"] }
reqwest = { version = "0.12", features = ["blocking"] }
reqwest = { version = "0.12", features = ["blocking", "json"] }
colored = "2.1.0"
serde = "1.0.207"
serde_json = "1.0.124"

[lib]
name = "exqs"
name = "nebby"
path = "src/lib.rs"
156 changes: 49 additions & 107 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,122 +1,64 @@
# Excel Quick Scan
# Nebby 🤥

## WORK IN PROGRESS
Nebby is a command-line tool for quickly reviewing basic information about remote Excel (xlsx) files and making simple API GET requests.

A simple CLI tool named Excel Quick Scan (ExQS).
> [!NOTE]
> Nebby is currently under active development. Features and commands may change as the project evolves.
This is a very basic tool that provides basic information about remote excel files.
## Usage

This is a project for me to practice Rust but I may make it available as a package in the future.
```
nebb <COMMAND>
```

## It currently only has 2 basic commands:
## Commands

```zsh
exqs basic --url "URL to Excel File here"
### `basic`
Display basic information about an Excel file.
```
nebb basic <URL>
```

```zsh
exqs format --url "URL to Excel File here"
### `format`
Check formatting of an Excel file.
```
nebb format <URL>
```

## Example Output for exqs basic / exqs basic index:

```text
Sheet Name: 2023
Total number of columns: 7
Total number of rows: 76
┌───────────────────────────────────────────────┬───────────┐
│ Column Headers ┆ Data Type │
╞═══════════════════════════════════════════════╪═══════════╡
│ Column 1: GENDER ┆ String │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ Column 2: POSTCODE ┆ String │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ Column 3: DOD ┆ Unknown │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ Column 4: AGE ┆ Float │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ Column 5: FUNERAL COST ┆ Float │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ Column 6: COSTS RECOVERED ┆ Float │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌┤
│ Column 7: DATE REFERRED TO TREASURY SOLICITOR ┆ String │
└───────────────────────────────────────────────┴───────────┘
Data Row 1: MALE LS25 41619 72 1590 1590 41900
Data Row 2: MALE LS22 41625 69 1350.54 1350.54 NOT REFERRED
Data Row 3: MALE LS8 41628 77 1702 0 NOT REFERRED
Data Row 4: MALE LS11 41653 63 2270 1673.4 NOT REFERRED
Data Row 5: MALE LS6 41654 54 1307 0 NOT REFERRED
Data Row 6: FEMALE LS12 41655 91 1474 1474 41767
Data Row 7: MALE LS14 41658 89 1630 1630 NOT REFERRED
Data Row 8: MALE LS12 41673 66 1378.5 1378.5 NOT REFERRED
Data Row 9: MALE LS3 41684 56 1660.64 855.49 NOT REFERRED
Data Row 10: FEMALE LS9 41689 46 1266 215.24 NOT REFERRED
### `quick-view`
Quick view of an Excel file.
```
nebb quick-view <URL>
```

## Example Output for exqs format:

```text
Analysing sheet: Cover sheet
Formatting issues:
- No header row found at all
- Sheet contains 3 merged region(s)
Analysing sheet: Instructions
Formatting issues:
- The header is not on the first row. Found on row 12
- Sheet contains 11 merged region(s)
Analysing sheet: Overview
Formatting issues:
- The header is not on the first row. Found on row 4
Analysing sheet: Resilience
Formatting issues:
- The header is not on the first row. Found on row 6
- Sheet contains 1 merged region(s)
Analysing sheet: Buildings and Energy
Formatting issues:
- The header is not on the first row. Found on row 6
- Sheet contains 1 merged region(s)
Analysing sheet: Transport
Formatting issues:
- The header is not on the first row. Found on row 6
- Sheet contains 1 merged region(s)
Analysing sheet: Waste
Formatting issues:
- The header is not on the first row. Found on row 6
- Sheet contains 1 merged region(s)
Analysing sheet: People
Formatting issues:
- The header is not on the first row. Found on row 6
- Sheet contains 1 merged region(s)
Analysing sheet: EqIA
Formatting issues:
- The header is not on the first row. Found on row 3
Analysing sheet: Results
Formatting issues:
- The header is not on the first row. Found on row 7
- Sheet contains 1 merged region(s)
Analysing sheet: Guidance
No formatting issues found.
Analysing sheet: Lists
No formatting issues found.
Analysing sheet: Background lookup tables
No formatting issues found.
Successfully Processed formatting!
### `basic-idx`
Display basic information about an Excel file with a specified header index.
```
nebb basic-idx <URL> [--header-index <INDEX>]
```

## Example output for exqs quick view:

```text
Sheet: Sheet1
--------------------
Property.. Uprn Account .. Address Postcode Empty Liabilit.. Empty from Exemptio.. Rateable.. Vo Prop .. Vo Propd..
20101143.. 72563680 THE THAC.. THACKRAY.. LS9 7LN Occupied.. 40269 60500 EM1 MUSEUM A..
20101595.. 72768691 SKYLORD .. 116-118 .. LS8 5NA Occupied.. 42856 10750 CS SHOP AND..
20101723.. 72522137 HANG WON.. 21 BLENH.. LS2 9HJ Occupied.. 44228 75000 CS SHOP AND..
20101723.. 72022950 NOODLEST.. 27 BLENH.. LS2 9HD Occupied.. 43424 29250 CS SHOP AND..
20101726.. 72022901 YORKSHIR.. BSMT GRO.. LS2 9HZ Occupied.. 41820 30500 CO OFFICES ..
20101726.. 72745783 HESHUO LTD GROUND F.. LS2 9HZ Occupied.. 44652 16000 CR RESTAURA..
20101726.. 72745782 HESHUO LTD BASEMENT.. LS2 9HZ Occupied.. 44652 9100 CR1 CAFE AND..
20101726.. 72744812 AKSHARMU.. GROUND F.. LS2 9HD Occupied.. 44985 35750 CS SHOP AND..
20102443.. 72557839 M. B. LO.. ST ANDRE.. LS3 1JX Occupied.. 40269 23250 CW WAREHOUS..
... only showing 10 rows out of approximately 22809
### `basic-json`
Make a basic API GET request and display the JSON response.
```
nebb basic-json <URL>
```

## Options

- `-h`, `--help`: Print help information
- `-V`, `--version`: Print version information

## Roadmap

- [ ] Add support for additional file formats
- [ ] Enhance JSON processing capabilities
- [ ] Implement DataFrame support
- [ ] TBC

## Author

Christopher Carlon

## Version

0.1.0
6 changes: 3 additions & 3 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ cargo clean
cargo build --release

# Install the binary
sudo cp target/release/exqs /usr/local/bin/
sudo cp target/release/nebb /usr/local/bin/

# Verify the installation
which exqs
which nebb

echo "exqs has been rebuilt and installed successfully!"
echo "nebby has been rebuilt and installed successfully!"
21 changes: 21 additions & 0 deletions makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Makefile for Nebby GitHub Release and Tagging

# Variables
VERSION := $(shell cargo pkgid | cut -d# -f2 | cut -d: -f2)

.PHONY: release

release:
@echo "Creating release $(VERSION)..."
@if [ -z "$(VERSION)" ]; then echo "Error: VERSION is not set"; exit 1; fi

# Create a new tag
git tag -a v$(VERSION) -m "Release version $(VERSION)"
git push origin v$(VERSION)

# Create GitHub release
gh release create v$(VERSION) \
--title "Nebb v$(VERSION)" \
--notes "Release notes for version $(VERSION)"

@echo "Release v$(VERSION) created and published on GitHub"
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// remote_file_functions.rs
// src/excel_file_functions.rs
use calamine::{DataType, Reader, Xlsx};
use colored::Colorize;
use comfy_table::{Attribute, Cell, Color, Table};
Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
// src/lib.rs
pub mod remote_file_functions;
pub mod excel_file_functions;
pub mod reqwest_functions;
94 changes: 55 additions & 39 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,85 +1,101 @@
// src/main.rs
mod remote_file_functions;
mod excel_file_functions;
mod reqwest_functions;
use clap::{Parser, Subcommand};
use colored::Colorize;
use remote_file_functions::{
use excel_file_functions::{
analyze_excel_formatting, display_remote_basic_info,
display_remote_basic_info_specify_header_idx, excel_quick_view, fetch_remote_file,
};
use reqwest_functions::simple_api_get_reqwest;

#[derive(Parser, Debug)]
#[command(author = "Christopher Carlon", version = "0.1.0", about = "Excel Quick Scan - quickly review basic information about any xlsx file", long_about = None)]
#[command(author = "Christopher Carlon", version = "0.1.0", about = "Nebby - quickly review basic information about remote xlsx files and API GET requests", long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}

#[derive(Subcommand, Debug)]
enum Commands {
/// Display basic information about the Excel file
/// Display basic information about an Excel file
Basic {
/// URL of the Excel file
#[arg(short, long)]
url: String,
},
/// Check formatting of the Excel file
/// Check formatting of an Excel file
Format {
/// URL of the Excel file
#[arg(short, long)]
url: String,
},
/// Quick view of the Excel file
/// Quick view of an Excel file
QuickView {
/// URL of the Excel file
#[arg(short, long)]
url: String,
},
/// Experimental basic information feature - add --header-index int to the end
/// Experimental basic information feature with specified header index
BasicIdx {
/// URL of the Excel file
#[arg(short, long)]
url: String,

/// Index of the header row (0-based)
#[arg(short, long, default_value = "0")]
header_index: usize,
},
/// Experimental basic API request feature
BasicJson {
/// API Endpoint
url: String,
},
}

fn main() {
fn main() -> Result<(), Box<dyn std::error::Error>> {
let cli = Cli::parse();
match &cli.command {
Commands::Basic { url } => process_url(url, display_remote_basic_info, "basic info"),
Commands::Format { url } => process_url(url, analyze_excel_formatting, "formatting"),
Commands::QuickView { url } => process_url(url, excel_quick_view, "quick view"),
Commands::BasicIdx { url, header_index } => process_url(
url,
|content| display_remote_basic_info_specify_header_idx(content, *header_index),
"basic info experimental",
),
Commands::Basic { url } => process_excel(url, "basic info"),
Commands::Format { url } => process_excel(url, "formatting"),
Commands::QuickView { url } => process_excel(url, "quick view"),
Commands::BasicIdx { url, header_index } => process_excel_with_header(url, *header_index),
Commands::BasicJson { url } => process_json(url),
}
}

fn process_url<F>(url: &str, process_fn: F, operation: &str)
where
F: Fn(Vec<u8>) -> Result<(), Box<dyn std::error::Error>>,
{
fn process_json(url: &str) -> Result<(), Box<dyn std::error::Error>> {
validate_url(url)?;
println!("{}", "Processing JSON...".blue());
simple_api_get_reqwest(url)
}

fn process_excel(url: &str, operation: &str) -> Result<(), Box<dyn std::error::Error>> {
validate_url(url)?;
println!("{}", format!("Processing Excel {}...", operation).blue());
let bytes = fetch_remote_file(url)?;
match operation {
"basic info" => display_remote_basic_info(bytes),
"formatting" => analyze_excel_formatting(bytes),
"quick view" => excel_quick_view(bytes),
_ => Err("Unknown operation".into()),
}
}

fn process_excel_with_header(
url: &str,
header_index: usize,
) -> Result<(), Box<dyn std::error::Error>> {
validate_url(url)?;
println!(
"{}",
format!("Processing Excel with header index {}...", header_index).blue()
);
let bytes = fetch_remote_file(url)?;
display_remote_basic_info_specify_header_idx(bytes, header_index)
}

fn validate_url(url: &str) -> Result<(), Box<dyn std::error::Error>> {
if url.is_empty() {
eprintln!("{}", "Error: URL cannot be empty".red());
return;
return Err("Error: URL cannot be empty".into());
}
if !url.starts_with("http://") && !url.starts_with("https://") {
eprintln!("{}", "Error: URL must start with http:// or https://".red());
return;
}
match fetch_remote_file(url) {
Ok(content) => match process_fn(content) {
Ok(_) => println!(
"{}",
format!("Successfully Processed {}!", operation).green()
),
Err(e) => eprintln!("{}", format!("Error processing file content: {}", e).red()),
},
Err(e) => eprintln!("{}", format!("Error fetching file from URL: {}", e).red()),
return Err("Error: URL must start with http:// or https://".into());
}
Ok(())
}
Loading

0 comments on commit 88f393b

Please sign in to comment.