Commit bb9bbe82 by Ivan Lan

feat: 数据好像对了

parent 49c7e59a
require 'active_support'
require "active_support/core_ext/hash"
require "active_support/core_ext/object"
require "tallty_import_export/version"
require 'axlsx'
require 'redis'
require 'tallty_form'
# require 'tallty_form'
require 'attr_json'
module TalltyImportExport
......@@ -18,6 +20,7 @@ module TalltyImportExport
autoload :Excel
autoload :Attr
autoload :ExportPayload
autoload :ExportForm
class Error < StandardError; end
......
......@@ -17,20 +17,23 @@ module TalltyImportExport
attr_json :proc, ActiveModel::Type::Value.new, array: true
attr_json :children, self.to_type, array: true
def depth
children&.count.to_i + 1
end
attr_accessor :depth, :parent_path, :seq
# 取叶子结点,获取到excel表格的宽度
def leaves
if children.present?
children.flat_map do |child|
child.leaves
end
def calcute_flatten_value _depth, _parent_path
@depth = _depth
@parent_path = _parent_path
if children
children.map do |child|
child.calcute_flatten_value(_depth + 1, [*_parent_path, self])
end.compact.flatten
else
[self]
end
end
def seq
@seq ||= SecureRandom.uuid
end
end
class ExportHeader
......@@ -39,17 +42,11 @@ module TalltyImportExport
attr_json :items, ExportHeaderItem.to_type, array: true
def depth
items.map(&:depth).max
def flatten_value
items.map do |item|
item.calcute_flatten_value(0, [])
end.flatten
end
# def height payload
# items.map do |item|
# TalltyImportExport::ExportPayload.new(header: item, payload: payload[item.key])
# end.map do |export_payload|
# export_payload.height
# end.max
# end
end
end
end
module TalltyImportExport
class ExportForm < TalltyImportExport::Export
def initialize
super({})
end
class << self
def form_transfer_to_headers form
end
end
def export_workbook workbook, association_records, **options
# excel导出样式
# alignment = { vertical: :center, horizontal: :center }
# border = { color: '969696', style: :thin }
# title1 = workbook.styles.add_style(alignment: alignment, border: border, sz: 12, b: true)
# title2 = workbook.styles.add_style(alignment: alignment, border: border, bg_color: "2a5caa", sz: 12, fg_color: "fffffb")
# title3 = workbook.styles.add_style(alignment: alignment.merge(wrap_text: true), border: border, sz: 10)
headers = export_headers_result **options
p headers.flatten_value.map(&:key)
# _sheet_name = respond_to?(:sheet_name) ? self.sheet_name : nil
# workbook.add_worksheet(name: _sheet_name) do |sheet|
# if respond_to?(:first_header)
# row_index = Axlsx.col_ref(headers.size - 1)
# sheet.merge_cells("A1:#{row_index}1")
# sheet.add_row [first_header], style: title1, height: 30
# end
# sheet.add_row headers.map{|header| header[:name]}, style: title2, height: 25
# last_row = nil
# merge_column_hash = {}
# first_content_row_index = respond_to?(:first_header) ? 2 : 1
index = 0
association_records.each do |association_record|
records = @each_method.present? ?
(try_method(association_record, @each_method) || [nil]) :
[association_record]
records.each do |record|
row = []
formats = []
index += 1
lines = TalltyImportExport::ExportPayload.new(record, headers: headers) do |payload, header|
# p "payload: #{payload} -- header[:key] #{header[:key]}"
_data = header[:source] ?
handle_data(association_record, header, index) :
handle_data(payload, header, index)
end.lines
result = []
lines.transpose.map do |transposed_line|
line = transposed_line
while line[0].nil?
line.shift
line.push(false)
end
line
# transposed_line.compact
end.transpose.each do |line|
if line.select(&:itself).count > 0
result << line.map { |x| x || '________' }
end
end
# result = []
# cache[0].length.times do
# cache.each_with_index do |line, index|
# result[index] = [] unless result[index]
# result[index] << line[index]
# end
# end
p '----------------------------------------------------------------'
result.uniq.sort.each { |x| p x }
# headers.each_with_index do |header, col_index|
# _data = header[:source] ?
# handle_data(association_record, header, index) :
# handle_data(record, header, index)
# if header[:merge].present? && last_row.present? && _data == last_row[col_index]
# # 这里使用二维数组,每个数组里都是列内容相同的各行
# merge_column_hash[col_index] ||= []
# if merge_column_hash[col_index].last&.last == index + first_content_row_index - 1
# # 说明内容和上面的是延续的,继续加入之前的数组
# merge_column_hash[col_index].last << index + first_content_row_index
# else
# merge_column_hash[col_index] << [index + first_content_row_index - 1, index + first_content_row_index]
# end
# end
# row.push(_data)
# formats.push(header[:format]&.to_sym || (_data.is_a?(String) ? :string : nil))
# end
# sheet.add_row row, style: title3, height: @row_height, types: formats
# last_row = row
end
end
# # 需要根据column进行多行的内容合并
# if merge_column_hash.present?
# merge_column_hash.each do |col_index, row_arr|
# row_arr.each do |arr|
# sheet.merge_cells(
# Axlsx::cell_r(col_index, arr.first) + ':' + Axlsx::cell_r(col_index, arr.last)
# )
# end
# end
# end
# sheet.column_widths(*headers.map{|header| (header[:width] || @width).to_f})
# end
end
def export_headers_result **options
@headers = options[:headers]
super(**options)
@headers = TalltyImportExport::Attr::ExportHeader.new({ items: @headers })
end
end
end
# class TalltyImportExport::ExportPayload
# # header: 导出时候使用的配置模型
# # payload: 对应的单行数据抽取,如果是list属性,则payload是一个array
# attr_accessor :header, :payload, :children, :parent
# def initialize(header:, payload:, parent: nil, children: [])
# @header = header
# @payload = payload
# @children = []
# @parent = parent
# # 递归生成
# if header.is_a?(TalltyImportExport::Attr::ExportHeader)
# @children = header.items.map do |header_item|
# self.class.new(
# header: header_item,
# payload: payload_value(header: header_item, payload: payload),
# parent: self
# )
# end
# else
# if header.children.present?
# @children = header.children.map do |header_item|
# self.class.new(
# header: header_item,
# payload: payload_value(header: header_item, payload: payload),
# parent: self
# )
# end
# end
# end
# end
# def height
# return 0 if payload.blank?
# if header.children.blank?
# # 单属性,如果有值,为1,没有值为0
# payload.present? ? 1 : 0
# else
# # list属性,payload是array
# # 高度是表格里所有属性的height的最大值
# children_height_arr = header.children.map do |header_child|
# Array(payload).map do |payload_child|
# self.class.new(
# header: header_child,
# payload: payload_value(header: header_child, payload: payload_child),
# ).height
# end.sum
# end.max
# end
# end
# # TODO 获取值的方法
# def payload_value header:, payload:
# payload&.dig(header.key)
# end
# end
class TalltyImportExport::ExportPayload
# header: 导出时候使用的配置模型
# payload: 对应的单行数据抽取,如果是list属性,则payload是一个array
attr_accessor :header, :payload, :children, :parent
attr_reader :value, :context
def initialize(header:, payload:, parent: nil, children: [])
def initialize(val, headers:, &value_handler)
@value = TalltyImportExport::ExportPayload::Value.new(val)
@headers = headers.items # TalltyImportExport::Attr::ExportHeaderItem array
@flatten_headers = headers.flatten_value
@value_handler = value_handler
@context = {
# header_seq_to_cell_seq_to_header_seq_to_value_mapping: {},
value_seq_to_header_seq_to_value: {},
# header_seq_to_header_mapping: @headers.reduce({}) do |out, header|
# out[header.seq] = header
# out
# end,
# header_seq_to_children_mapping: @headers.reduce({}) do |out, header|
# out[header.seq] = header.children
# out
# end,
flatten_headers: @flatten_headers,
}
end
def lines
cell_columns = @headers.map do |header|
TalltyImportExport::ExportPayload::CellColumn.new(
header,
self.value,
@context,
&@value_handler
)
end
max_height_cell_column = cell_columns.map(&:flatten_cells).max do |a, b|
a.count <=> b.count
end
max_height_cell_column.map(&:grow_to_line)
end
end
class TalltyImportExport::ExportPayload::Value
attr_reader :value, :seq_chain
def initialize val, seq_chain=[]
@value = val
@seq_chain = [*seq_chain, seq]
# flatten_cells.each do |cell|
# context[:cell_seq_to_header_seq_to_value][cell.seq] = {} unless context[:cell_seq_to_header_seq_to_value][cell.seq]
# context[:cell_seq_to_header_seq_to_value][cell.seq][header.seq] = value
end
def seq
@seq ||= SecureRandom.uuid
end
end
# 一个 竖列
class TalltyImportExport::ExportPayload::CellColumn
attr_reader :header, :payload, :context, :cell_clusters, :flatten_cells
def initialize header, value, context, &value_handler
@header = header
@payload = payload
@children = []
@parent = parent
# 递归生成
if header.is_a?(TalltyImportExport::Attr::ExportHeader)
@children = header.items.map do |header_item|
self.class.new(
header: header_item,
payload: payload_value(header: header_item, payload: payload),
parent: self
@value = value
@context = context
@cell_clusters = []
@value_handler = value_handler
if header.children
@cell_clusters = @value.value[header.key.to_sym].map do |val|
TalltyImportExport::ExportPayload::Cell.new(
@header,
TalltyImportExport::ExportPayload::Value.new(val, @value.seq_chain),
@context,
&@value_handler
)
end
else
if header.children.present?
@children = header.children.map do |header_item|
self.class.new(
header: header_item,
payload: payload_value(header: header_item, payload: payload),
parent: self
)
end
@cell_clusters = [
TalltyImportExport::ExportPayload::Cell.new(
@header,
TalltyImportExport::ExportPayload::Value.new(
@value_handler.call(@value.value, @header.as_json.symbolize_keys),
@value.seq_chain,
),
@context,
&@value_handler
)
]
end
@flatten_cells = []
cell_divise
end
def cell_divise
@flatten_cells = @cell_clusters.map do |cell_cluster|
cell_cluster.divise.cell_cluster
end.flatten
self
end
end
class TalltyImportExport::ExportPayload::Cell
attr_accessor :cell_cluster, :val, :header, :parent_path
# cell_cluster 是表格纵向 集合
# cell_the_same_line 是表格横向 集合
def initialize header, value, context, parent_path=[], &value_handler
@value = value
@header = header
@value_handler = value_handler
# context
@context = context
# unless (@context[:header_seq_to_cell_seq_to_header_seq_to_value_mapping][header.seq])
# @context[:header_seq_to_cell_seq_to_header_seq_to_value_mapping][header.seq] = {}
# end
# @context[:header_seq_to_cell_seq_to_header_seq_to_value_mapping][header.seq][seq] = value
value.seq_chain.each do |s|
unless (@context[:value_seq_to_header_seq_to_value][s])
@context[:value_seq_to_header_seq_to_value][s] = {}
end
@context[:value_seq_to_header_seq_to_value][s][header.seq] = value.value
end
# parent
@parent_path = parent_path
@cell_cluster = []
end
def height
return 0 if payload.blank?
def seq
@seq ||= SecureRandom.uuid
end
def heredity_chain
[*self.parent_path, self]
end
if header.children.blank?
# 单属性,如果有值,为1,没有值为0
payload.present? ? 1 : 0
def divise
if @header.children.present?
new_cells = @header.children.map do |child_header|
if (child_header.children.present?)
val = @value.value[child_header.key.to_sym]
val.map do |val|
TalltyImportExport::ExportPayload::Cell.new(
child_header,
TalltyImportExport::ExportPayload::Value.new(val, @value.seq_chain),
@context,
[*self.parent_path, self],
&@value_handler
)
end
else
val = @value_handler.call(@value.value, child_header.as_json.symbolize_keys)
TalltyImportExport::ExportPayload::Cell.new(
child_header,
TalltyImportExport::ExportPayload::Value.new(val, @value.seq_chain),
@context,
[*self.parent_path, self],
&@value_handler
)
end
end.flatten
new_cells.each(&:divise)
@cell_cluster.concat(new_cells.map(&:cell_cluster))
else
# list属性,payload是array
# 高度是表格里所有属性的height的最大值
children_height_arr = header.children.map do |header_child|
Array(payload).map do |payload_child|
self.class.new(
header: header_child,
payload: payload_value(header: header_child, payload: payload_child),
).height
end.sum
end.max
@cell_cluster = [self]
end
end
# TODO 获取值的方法
def payload_value header:, payload:
payload&.dig(header.key)
self
end
def grow_to_line
# heredity_chain_seq = heredity_chain.map(&:seq)
@context[:flatten_headers].map do |header|
# cell_seq_to_header_seq_to_value_mapping = @context[:header_seq_to_cell_seq_to_header_seq_to_value_mapping][header.seq]
# target_val = nil
# heredity_chain_seq.each do |seq|
# if cell_seq_to_header_seq_to_value_mapping[seq]
# target_val = cell_seq_to_header_seq_to_value_mapping[seq]
# end
# end
# target_val
target_val = nil
@value.seq_chain.each do |seq|
if @context[:value_seq_to_header_seq_to_value][seq]&.[](header.seq)
target_val = @context[:value_seq_to_header_seq_to_value][seq][header.seq]
end
end
target_val
end
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment