Current section

Files

Jump to
xlsx_reader lib xlsx_reader parsers styles_parser.ex
Raw

lib/xlsx_reader/parsers/styles_parser.ex

defmodule XlsxReader.Parsers.StylesParser do
@moduledoc false
# Parses SpreadsheetML style definitions.
#
# It extracts the relevant subset of style definitions in order to build
# a `style_types` array which is used to look up the cell value format
# for type conversions.
@behaviour Saxy.Handler
alias XlsxReader.{Array, Styles}
alias XlsxReader.Parsers.Utils
defmodule State do
@moduledoc false
defstruct collect_xf: false,
style_types: [],
custom_formats: %{},
supported_custom_formats: []
end
def parse(xml, supported_custom_formats \\ []) do
with {:ok, state} <-
Saxy.parse_string(xml, __MODULE__, %State{
supported_custom_formats: supported_custom_formats
}) do
{:ok, state.style_types, state.custom_formats}
end
end
@impl Saxy.Handler
def handle_event(:start_document, _prolog, state) do
{:ok, state}
end
@impl Saxy.Handler
def handle_event(:end_document, _data, state) do
{:ok, state}
end
@impl Saxy.Handler
def handle_event(:start_element, {"numFmt", attributes}, state) do
num_fmt_id = Utils.get_attribute(attributes, "numFmtId")
format_code = Utils.get_attribute(attributes, "formatCode")
{:ok, %{state | custom_formats: Map.put(state.custom_formats, num_fmt_id, format_code)}}
end
@impl Saxy.Handler
def handle_event(:start_element, {"cellXfs", _attributes}, state) do
{:ok, %{state | collect_xf: true}}
end
@impl Saxy.Handler
def handle_event(:start_element, {"xf", attributes}, %{collect_xf: true} = state) do
num_fmt_id = Utils.get_attribute(attributes, "numFmtId")
{:ok,
%{
state
| style_types: [
Styles.get_style_type(
num_fmt_id,
state.custom_formats,
state.supported_custom_formats
)
| state.style_types
]
}}
end
@impl Saxy.Handler
def handle_event(:start_element, _element, state) do
{:ok, state}
end
@impl Saxy.Handler
def handle_event(:end_element, "cellXfs", state) do
{:ok,
%{state | collect_xf: false, style_types: Array.from_list(Enum.reverse(state.style_types))}}
end
@impl Saxy.Handler
def handle_event(:end_element, _name, state) do
{:ok, state}
end
@impl Saxy.Handler
def handle_event(:characters, _chars, state) do
{:ok, state}
end
end