Registry / RepositoryTypeScriptRustPython
Rollpie
ReadmeFiles
Versions
Info
Download
0.1.199.9 KB2026-09-230.1.098.9 KB2026-09-14
Version
0.1.1
Copyright
Rollpie, Irohabook
Publisher
math
Published
2026-09-23
Size
99.9 KB
Downloads
15
Checksum
e691f02f331393c7b5c3406746caa7ed2636c7af24b1cef422bc957ed16ecd74
Dependencies
None

cell.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//! セルの値と、A1 の形の参照


/// セルに入っているもの
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
    /// 何も入っていない
    Empty,
    /// 数。日付も数で入っている。日付かどうかは書式で決まる
    Number(f64),
    /// 文字
    Text(String),
    /// 真偽
    Boolean(bool),
    /// #N/A や #DIV/0! のようなエラー
    Error(String),
}


impl Value {
    /// 数として読む。数でなければ None
    pub fn number(&self) -> Option<f64> {
        match self {
            Value::Number(value) => Some(*value),
            _ => None,
        }
    }

    /// 文字として読む。文字でなければ None
    pub fn text(&self) -> Option<&str> {
        match self {
            Value::Text(value) => Some(value),
            _ => None,
        }
    }

    /// 何も入っていないか
    pub fn is_empty(&self) -> bool {
        *self == Value::Empty
    }
}


/// セル 1 つ
#[derive(Debug, Clone, PartialEq)]
pub struct Cell {
    /// 列。1 から始まる
    pub column: u32,
    /// 書式の番号。styles.xml の cellXfs での位置
    pub style: u32,
    /// 入っているもの
    pub value: Value,
    /// 数式。ないときは空。`=` は含まない
    pub formula: String,
}


/// 行 1 つ。値の入っているセルだけが、列の順に並ぶ
#[derive(Debug, Clone, Default)]
pub struct Row {
    /// 行番号。1 から始まる
    pub number: u32,
    /// この行のセル
    pub cell: Vec<Cell>,
}


impl Row {
    /// 列で引く。そのセルがなければ None
    pub fn at(&self, column: u32) -> Option<&Cell> {
        // 列の順に並んでいるので、二分で引ける
        match self.cell.binary_search_by(|one| one.column.cmp(&column)) {
            Ok(index) => Some(&self.cell[index]),
            Err(_) => None,
        }
    }
}


/// A1 の形の参照から列を読む。1 から始まる。読めなければ 0
pub fn column_of(reference: &str) -> u32 {
    let mut result = 0;

    for value in reference.bytes() {
        if !value.is_ascii_alphabetic() {
            break;
        }

        result = result * 26 + (value.to_ascii_uppercase() - b'A' + 1) as u32;
    }

    result
}


/// A1 の形の参照から行を読む。1 から始まる。読めなければ 0
pub fn row_of(reference: &str) -> u32 {
    let mut result = 0;
    let mut found = false;

    for value in reference.bytes() {
        if value.is_ascii_digit() {
            result = result * 10 + (value - b'0') as u32;
            found = true;
            continue;
        }

        if found {
            break;
        }
    }

    result
}


/// 列の番号を A、B、… AA の形に直す
pub fn letter_of(column: u32) -> String {
    if column == 0 {
        return String::new();
    }

    let mut rest = column;
    let mut result = Vec::new();

    while rest > 0 {
        let step = (rest - 1) % 26;
        result.push(b'A' + step as u8);
        rest = (rest - 1) / 26;
    }

    result.reverse();
    String::from_utf8(result).unwrap_or_default()
}