8 个版本 (5 个重大变更)
0.6.2 | 2023 年 2 月 6 日 |
---|---|
0.6.1 | 2022 年 4 月 5 日 |
0.5.0 | 2022 年 2 月 27 日 |
0.4.0 | 2022 年 2 月 25 日 |
0.1.0 | 2022 年 2 月 7 日 |
#49 in #api-wrapper
24 个月下载量
150KB
2.5K SLoC
smartsheet-rs
smartsheet-rs 是一个 rust crate,它提供了一个异步包装器 API,使您能够轻松地与 Smartsheet API 2.0 交互。
这是一个为了学习 Rust 而制作的非官方 SDK,但我希望您也能从中获得乐趣——我知道我在为这个 crate 编写实现时确实有很多乐趣。
目录
入门指南
使用 smartsheet-rs
库入门很简单
-
在您的环境中设置 SMARTSHEET_ACCESS_TOKEN;您还可以使用
SmartsheetApi::from_token
构造函数显式设置令牌值。有关 Smartsheet API 文档中的 身份验证和访问令牌 的更多信息。 -
将这些依赖项添加到您的
Cargo.toml
[dependencies] smartsheet-rs = "0.6.2" tokio = { version = "1", features = ["rt-multi-thread", "macros"] }
-
将一些用法添加到您的应用程序中
use smartsheet_rs::SmartsheetApi; #[tokio::main] async fn main() -> std::result::Result<(), Box<dyn std::error::Error + Send + Sync>> { let smart = SmartsheetApi::from_env()?; println!("Created a Smartsheet API client"); let sheets = smart.list_sheets().await?; println!("Printing sheet names:"); for sheet in sheets.data { println!(" - {}", sheet.name); } Ok(()) }
实现的方法
目前已经实现了以下来自 官方文档 的 API 方法
您可以在 GitHub 上的项目仓库中的 examples/ 文件夹中查看这些 API 方法的示例用法。
更大的示例
在 SmartSheet API 中处理行和单元格时,一个突出的问题是 API 故意通过 ID 而不是标题或 列名 来标识列。
然而,作为人类,在处理数据时引用 列名 要自然和方便得多。为此,smartsheet-rs crate 提供了如 ColumnMapper
、CellGetter
和 RowGetter
等辅助 struct 实现,以简化与 Smartsheet API 的交互。
单元格
检索单元格
要按关联的列ID从行中检索单个单元格,您可以使用Row::get_cell_by_id
。
如果要按列名检索单个Cell
,您首先可以使用ColumnMapper
构建一个列名到ID的映射,然后与CellGetter
配对以从行中检索单元格。
以下是一个快速示例,说明这是如何工作的
use smartsheet_rs::{CellGetter, ColumnMapper, SmartsheetApi};
// TODO update these values as needed
const SHEET_ID: u64 = 1234567890;
const COLUMN_NAME: &str = "My Column";
// A simple type alias so as to DRY.
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
#[tokio::main]
async fn main() -> Result<()> {
let smart = SmartsheetApi::from_env()?;
let sheet = smart.get_sheet(SHEET_ID).await?;
// Create interchangeable name <-> id mappings for columns in the row
let cols = ColumnMapper::new(&sheet.columns);
// Create a `CellGetter` helper to find cells in a row by *Column Name*
let get_cell = CellGetter::new(&cols);
// Get the first row in the sheet. We could also access
// a row by index, like `&sheet.rows[i]` for example.
let first_row = sheet.rows.first().unwrap();
// Try to find a cell in the row by it's column name
match get_cell.by_name(first_row, COLUMN_NAME) {
Ok(cell) => println!("Here's the cell: {:#?}", *cell),
Err(e) => println!("Error: {}", e),
}
Ok(())
}
CellGetter::by_name
方法通过遍历行中的每个单元格,然后返回第一个匹配指定列名的单元格的列ID的Cell
。
如果需要通过列名从Row
中检索多个Cell
对象,最好首先为该列的每个列名构建一个映射到行中相应Cell
对象的映射。可以使用以下示例中的CellGetter::name_to_cell
方法来执行此操作。
let column_name_to_cell = get_cell.name_to_cell(row);
println!("{:#?}", column_name_to_cell);
// Prints:
// {
// "Column 1": Cell {...},
// "Column 2": Cell {...},
// ...
多联系人单元格
当处理更复杂的对象,例如MULTI_CONTACT
列类型的单元格时,可以使用辅助方法Cell::contacts
从单元格中提取联系信息。请注意,要检索每个联系人的电子邮件,需要传递包含include=objectValue
查询参数的include
参数以及相应的level
参数,以便收集完整的多联系人详细信息。
以下是代码的相关部分,演示了处理给定行中MULTI_CONTACT
单元格数据的理想方式
// Retrieve the sheet with `MULTI_CONTACT` info included, such as emails.
let sheet = smart.get_sheet_with_multi_contact_info(sheet_id).await?;
// Let's assume we retrieve the cell for the specified column from the first row.
let cell = get_cell.by_name(&sheet.rows[0], "My Multi-Contact Column")?;
// Now we create a list of `Contact` objects from the cell details.
let contacts = cell.contacts()?;
// Get the contact emails, as a comma-delimited string in the format
// *[email protected], [email protected]*
let emails = contacts.addrs_str();
// Get a list of contact name addresses, where each one as indicated
// in the RFC will be in the format `[display-name] angle-addr` --
// that is, for example, *John Doe <[email protected]>*
let names = contacts.name_addrs();
要查看完整的代码,请参阅项目存储库中的示例cell_multi_contact
:cell_multi_contact。
行
检索行
要按关联的行ID从工作表检索单个行,您可以使用Sheet::get_row_by_id
。
如果目标是找到与指定条件匹配的一个或多个行,则可以使用RowGetter
辅助程序使任务更加方便。
以下是一个简单示例,用于查找具有特定值的列中Cell
的第一个Row
,以及具有指定值的列中所有Row
。
use serde_json::to_string_pretty;
use smartsheet_rs::{ColumnMapper, RowGetter, SmartsheetApi};
// TODO update these values as needed
const SHEET_ID: u64 = 1234567890;
// A simple type alias so as to DRY.
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
#[tokio::main]
async fn main() -> Result<()> {
let smart = SmartsheetApi::from_env()?;
let sheet = smart.get_sheet(SHEET_ID).await?;
let cols = ColumnMapper::from(&sheet);
// Create a `RowGetter` helper to find rows in a sheet by a condition
// based on a *Column Name* and *Column Value*.
let get_row = RowGetter::new(&sheet.rows, &cols);
let row = get_row
// Note: "My Value" can be either a String, Number, or Boolean.
.where_eq("Column 1", "My Value")?
// Only want to get the first row which matches the condition.
.first()?;
let rows = get_row
// Retrieve *all* rows that *do not* match the specified cell value.
.where_ne("Column 2", 123.45)?
.find_all()?;
// Print the match for the first query
println!("Here's the first result: {:#?}", *row);
// Print the list of rows that match the second query
println!("Found {} Rows that match the second condition:", rows.len());
println!("{}", to_string_pretty(&rows)?);
Ok(())
}
类似于从Row
中检索多个Cell
对象的示例,可以使用Sheet::id_to_row
方法构建每个行ID与其相关Row
对象的映射。这在使用行ID值搜索多个Row
对象时很有用。
创建行
要添加或更新行,需要构建一个单元格列表以更新其值,然后将单元格添加到行中。可以使用辅助结构体CellFactory
来构建要添加到Row
中的Cell
对象。
请注意,要添加行,需要传递一个位置指定符属性。要更新行,我们只需要设置每个行的行ID。
以下是一个将新的Row
添加到工作表的示例。在这里,我们将位置指定符to_top
设置为将新行发送到工作表的顶部。
use serde_json::to_string_pretty;
use smartsheet_rs::models::{Decision, LightPicker, Row, RowLocationSpecifier};
use smartsheet_rs::{CellFactory, ColumnMapper, SmartsheetApi};
// TODO update these values as needed
const SHEET_ID: u64 = 1234567890;
// A simple type alias so as to DRY.
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;
#[tokio::main]
async fn main() -> Result<()> {
let smart = SmartsheetApi::from_env()?;
let index_result = smart.list_columns(SHEET_ID).await?;
let cols = ColumnMapper::from(&index_result);
// Create a `CellFactory` helper to build out a list of cells to create
// a `Row` from.
let make = CellFactory::new(&cols);
// Create the `Cell` objects to add here.
let cells = [
make.cell("Text/Number Column", 123.45)?,
make.cell("Symbol Column #1", LightPicker::Yellow)?,
make.cell("Symbol Column #2", Decision::Hold)?,
make.cell("Checkbox Column", true)?,
make.contact_cell("Assigned To", "[email protected]")?,
make.url_hyperlink_cell("Link to Page", "Rust Homepage", "https://rust-lang.net.cn")?,
make.multi_picklist_cell(
"Multi Dropdown Column",
&["Hello, world!", "Testing", "1 2 3"],
)?,
];
// Create a new `Row` from the list of `Cell` objects.
let row_to_add = Row::from(&cells);
println!("Input Object: {}", to_string_pretty(&row_to_add)?);
// Add the Rows to the Sheet
let _ = smart.add_rows(SHEET_ID, [row_to_add].to_top(true)).await?;
Ok(())
}
依赖项和功能
该库只使用所需的最小依赖项,以保持整体大小较小。此crate内部使用hyper
和hyper-rustls
,用于向Smartsheet API发起HTTPS请求。
虽然选择hyper-rustls
作为默认的TLS实现,因为它在为x86_64-unknown-linux-musl
目标交叉编译时没有问题,这对于AWS Lambda部署来说是常见的,但仍可以选择使用依赖OpenSSL的本地hyper-tls
实现。
为此,请禁用默认的"rust-tls"功能并启用"native-tls"功能
[dependencies]
smartsheet-rs = { version = "0.6.2", default-features = false, features = ["native-tls", "logging", "serde-std"] }
贡献
欢迎贡献!打开一个pull request来修复错误,或者打开一个issue来讨论新功能或变更。
有关更多信息,请查看文档中的贡献部分。
许可证
本项目自豪地采用MIT许可协议(LICENSE或http://opensource.org/licenses/MIT)。
smartsheet-rs
可根据MIT许可协议进行分发。贡献将在同一许可下接受。
作者
依赖项
~5–19MB
~276K SLoC