<?xml version="1.0" encoding="UTF-8"?>

<!-- ====================================================================== -->
<!-- = spswm.xml                                                          = -->
<!-- = standard speadsheet module - writer manual                         = -->
<!-- ====================================================================== -->
<!-- = This  program  is  free  software; you  can redistribute it and/or = -->
<!-- = modify it provided that this copyright notice is kept intact.      = -->
<!-- = This program is distributed in the hope that it will be useful but = -->
<!-- = without  any  warranty;  without  even  the  implied  warranty  of = -->
<!-- = merchantability or fitness for  a  particular purpose. In no event = -->
<!-- = shall  the  copyright  holder be liable for any  direct, indirect, = -->
<!-- = incidental  or special  damages arising  in any way out of the use = -->
<!-- = of this software.                                                  = -->
<!-- ====================================================================== -->
<!-- = copyright (c) 1999-2019 - amaury darsch                            = -->
<!-- ====================================================================== -->

<chapter module="sps" number="1">
  <title>Standard Spreadsheet Module</title>
  
  <p>
    The <em>Standard Spreadsheet</em> module is an original implementation
    that provides the necessary objects for designing a spreadsheet. A
    spreasheet acts a great interface which structure data in the form of
    record and sheets. Once structured, these data can be indexed,
    manipulated and exported into various formats.
  </p>

  <!-- section -->
  <section>
    <title>Spreadsheet concepts</title>

    <p>
      The sole purpose of using a spreadsheet is to collect various data
      and store them in such a way that they can be accessed
      later. Unlike standard spreadsheet system, the standard
      spreadsheet module does not place restrictions on the data
      organization.

      The spreadsheet module stores data in a hierarchical fashion. The
      basic data element is called a <em>cell</em>. A set of cells is
      a <em>record</em>. A set of records is a <em>sheet</em>. A set of
      sheets and records is a <em>folio</em>. 
    </p>

    <!-- cell and data -->
    <subsect>
      <title>Cell and data</title>

      <p>
	A <em>cell</em> is a data container. There is only one data
	element per cell. Eventually a name can be associated with a
	cell. The cell data can be any kind of literals. Such literals
	are integer, real, boolean, character or strings.
      </p>
    </subsect>

    <!-- record -->
    <subsect>
      <title>Record</title>

      <p>
	A <em>record</em> is a vector of cells. A record can be created
	by adding cell or simply by adding data. If the record has a
	predefined size, the cell or data can be set by indexing.
      </p>
    </subsect>

    <!-- sheet -->
    <subsect>
      <title>Sheet</title>

      <p>
	A <em>sheet</em> is a vector of records. A sheet can be created
	by adding record. Similarly, if the sheet has a predefined size,
	record cell or data can be added by indexing. A sheet can also
	be seen as a 2 dimensional array of cells. For the purpose of
	managing extra information, the sheet carry also several extra
	records, namely, the <em>marker record</em>, the <em>header
	record</em> and <em>footer record</em> as well as the <em>tag
	vector</em> and the <em>signature</em>.
      </p>
    </subsect>

    <!-- folio -->
    <subsect>
      <title>Folio</title>

      <p>
	A <em>folio</em> is a set of sheets and/or records. A folio
	of sheets permits to structure data in the form of tables. Since
	cell, record and table can have a name, it is possible to create
	link between various elements, thus creating a collection of
	structured data.
      </p>
    </subsect>
  </section>

  <!-- storage model -->
  <section>
    <title>Storage model</title>

    <p>
      There are several ways to integrate data. In the simplest form,
      data are integrated in a record list. A complex model can be built
      with a sheet. More complex models can also be designed by using a
      folio.
    </p>

    <!-- single record model -->
    <subsect>
      <title>Single record model</title>

      <p>
	With a single record model, the data are accumulated in a single
	array. This kind of data storing is particularly adapted for
	single list recording. As a single record, the basic search and
	sorting algorithm can be applied. For instance, a list name can
	be stored as a single record. With this view, there is no
	difference between a list, a vector and a record. The record can
	also be named.
      </p>
    </subsect>

    <!-- record importation -->
    <subsect>
      <title>Record importation</title>
      
      <p>
	Data are imported into the record, either by construction, list
	or stream. Since the record object is a serializeable object, the
	importation process is also performed automatically in the
	collection. The base record importation class implements a
	simple importation model based on blank separated
	literals. Complex importation models can be devised by
	derivation. A special case with a cons cell is also supported
	where the <em>car</em> is the cell name and the <em>cadr</em> is
	the cell object.
      </p>

      <example>
	# an example of file importation
	1   "a string" 'a'
	'b' ("cell name" 2) 123
      </example>

      <p>
	The previous example shows the file structure that can be used
	to import cell data. The fist line defines a record with 3
	cells. The second line defines also a record with 3 cells. The
	second cell is a named cell.
      </p>
    </subsect>

    <!-- record exportation -->
    <subsect>
      <title>Record exportation</title>

      <p>
	A record is an object that can be serialized. It can therefore
	be exported easily. However, in the serialized form, the record
	is in a binary form. It is also possible to walk through the
	record and exports, for each cell its literal form.
      </p>
    </subsect>
  </section>

  <!-- folio indexation -->
  <section>
    <title>Folio indexation</title>

    <p>
      There are various ways to access a folio by reference. Since a
      folio can contain several sheets, it seems natural to access them
      by tag. The other method is to index the cells in a
      cross-reference album in order to access rapidly.
    </p>

    <!-- sheet access model -->
    <subsect>
      <title>Sheet access model</title>

      <p>
	The sheet access model uses a tag to access one or several
	sheets in a folio. A tag is a string attached to a sheet. It is
	possible in a folio to have several sheet with the same tag. It
	is also possible to attach several tags to a sheet. When a folio
	is searched by tag, the first sheet that matches the tag is said
	to be the valid one. If all sheets that match the requested tag
	are needed, it is possible to create a derived folio with all
	sheets that match the requested tag.
      </p>
    </subsect>

    <!-- cell access model -->
    <subsect>
      <title>Cell access model</title>
      
      <p>
	The cell access model operates with a cross-reference table
	built with an index. An index is a multiple entry record that
	stores the cell location. A cell coordinate comprises the cell
	index in the record, the record index in the sheet and the sheet
	index in the folio. If an index contains multiple entries, this
	indicates that several cells are indexed. A cell cross-reference
	table is a collection of index. Generally the index name is the
	cell name. When the cross-reference table is built, all cell of
	interests are scanned and if a cell name exists, the cell is
	indexed in the cross-reference table. If there are several cells
	with the same name, the index length associated with the name is
	the number of cells with that name.
      </p>
    </subsect>

    <!-- search and access -->
    <subsect>
      <title>Search and access</title>

      <p>
	The methodology for searching is to decide whether a sheet or a
	cell should be accessible. If a sheet access is desired, the
	search by tag method is the preferred way. This method assumes
	that the requested sheet is structured in a particular way,
	known to the user. If a cell access seems more appropriate, a
	cross-reference table should be built first, and the search done
	from it. In the case of search by tag, the method is dynamic and
	operates well when sheets are added in a folio. When a
	cross-reference table is used, proper care should be taken to
	rebuild the cross-reference table when some sheets are added
	unless the user knows that there is no need for it.
      </p>
    </subsect>
  </section>

  <!-- folio object -->
  <section>
    <title>Folio object</title>

    <p>
      The <code>Folio</code> object is the primary object used for
      storing data. Although, a folio is a collection of sheets, it the
      primary object that should be created when manipulating such
      collection.
    </p>

    <!-- creating a folio -->
    <subsect>
      <title>Creating a folio</title>

      <p>
	The <code>Folio</code> object is built without argument. In this
	case, the folio is empty. A predicate is available for testing
	the <code>Folio</code> object.
      </p>

      <example>
	const sps (afnix:sps:Folio)
	afnix:sps:folio-p sps # true
      </example>

      <p>
	The constructor can operate also by name or by input
	stream. With a string, a new folio those name is the argument is
	created. By stream, a new folio is created and loaded with the
	input stream data. Eventually, the folio name can be set with the
	<code>set-name</code> command and retrieved with the
	<code>get-name</code> command.
      </p>

      <example>
	const sps (afnix:sps:Folio)
	sps:set-name "planets"
      </example>
    </subsect>
  </section>

  <!-- sheet object -->
  <section>
    <title>Sheet object</title>

    <p>
      The <code>Sheet</code> object is the primary object used to store
      data in a folio. Since a <code>Folio</code> object is a collection
      of sheets, a sheet can be manipulated either by getting getting it
      from the folio or by creating it independently and adding it into
      the folio.
    </p>

    <!-- creatig a sheet -->
    <subsect>
      <title>Creating a sheet</title>

      <p>
	An empty sheet can be created simply with or without
	name. Without argument, an unnamed sheet is created. Similar to
	the <code>Folio</code> class, the sheet name can be passed at
	construction or set with the <code>set-name</code> method. As
	usual a predicate is provided. 
      </p>

      <example>
	const sht (afnix:sps:Sheet)
	afnix:sps:sheet-p sht # true
      </example>

      <p>
	When the sheet is created, it can be added to the folio
	spreadsheet with the <code>add</code> method.
      </p>

      <example>
	const sht (afnix:sps:Sheet "data")
	sps:add sht
      </example>
    </subsect>

    <!-- adding data to the sheet -->
    <subsect>
      <title>Adding data to the sheet</title>

      <p>
	The process of adding data to a sheet is a straightforward
	operation with the <code>add-data</code> method or the
	<code>add</code> method. With the <code>add-data</code> method,
	data are added as literals. With the <code>add</code> method,
	data are added with the help of a record object.
      </p>

      <example>
	sht:add-data "Mercury"   4840 "1407:36"
	sht:add-data "Venus"    12400 "5819:51"
	sht:add-data "Earth"    12756 "23:56"
	sht:add-data "Mars"      6800 "24:37"
	sht:add-data "Jupiter" 142800 "9:50"
	sht:add-data "Saturn"  120800 "10:14"
	sht:add-data "Uranus"   47600 "10:49"
	sht:add-data "Neptune"  44600 "15:40"
	sht:add-data "Pluto"     5850 "153:17"
	sht:add-data "Sedna"     1800 "960:00"
      </example>

      <p>
	Data can be imported in a sheet by importation with an input
	stream. During the importation, the serialized data are decoded
	and placed sequentially in the stream.
      </p>
    </subsect>

    <!-- sheet sorting -->
    <subsect>
      <title>Sheet sorting</title>

      <p>
	A sheet can be sorted with the <code>sort</code> method. The
	<code>sort</code> method uses the first integer argument as the
	column number. The second optional argument is a boolean
	argument that selects the sorting method which can be ascending
	(by default) or descending if the flag is false.
      </p>

      <example>
	sht:sort 0
	sht:sort 1 false
      </example>
    </subsect>
  </section>

  <!-- record object -->
  <section>
    <title>Record object</title>

    <p>
      The <code>Record</code> object is an alternative to the sheet data
      filling. With the help of the <code>add</code> method, a record
      can be added to a sheet.
    </p>

    <!-- creating a record -->
    <subsect>
      <title>Creating a record</title>

      <p>
	A record is a named object that acts as a vector of cells. The
	record name can be set either by construction or with the
	<code>set-name</code> method. As usual a predicate is provided.
      </p>

      <example>
	const rcd (afnix:sps:Record)
	afnix:sps:record-p # true
      </example>
    </subsect>

    <!-- filling a record -->
    <subsect>
      <title>Filling a record</title>
      
      <p>
	A record can be filled either with literal data or
	<code>Cell</code> objects. In the first case, the cell is
	automatically created for each literal added to the record. The
	<code>add</code> method add a cell or literal to the record.
      </p>

      <example>
	const rcd (Record)
	rcd:add "Mercury" 4840 "1407:36"
      </example>

      <p>
	For data extraction, the <code>length</code> method returns the
	record length. Data can be extracted by index with either the
	<code>get</code> or <code>map</code> method. The <code>get</code>
	method returns the record cell while the <code>map</code> method
	returns the cell literal.
      </p>
    </subsect>
  </section>

  <!-- object search-->
  <section>
    <title>Object search</title>

    <p>
      The search methodology is divided either by sheet or cells. In a
      folio, the search is done in terms of sheets while the
      construction of a cross-reference table is required for searching
      cells.
    </p>

    <!-- searching in a folio -->
    <subsect>
      <title>Searching in a folio</title>
      
      <p>
	The <code>Folio</code> object provides the primary mean to search
	for sheet. The <code>find</code> and <code>lookup</code> methods
	return a sheet by tag. The first sheet that matches the tag is
	returned by these methods. The <code>find</code> method returns
	nil if the sheet cannot be found while the <code>lookup</code>
	method throws an exception.
      </p>

      <example>
	# get a sheet by tag
	const sheet (folio:lookup "the tag")
      </example>
      
      <p>
	If there are several sheets that matched the tag,
	the <code>filter</code> method is more appropriate. 
	The <code>filter</code> method returns a new folio that contains
	the sheet that matches the requested tag.
      </p>

      <example>
	# get a sub-folio by tag
	const sf (folio:filter "the tag")
      </example>
    </subsect>

    <!-- searching for a cell -->
    <subsect>
      <title>Searching for a cell</title>
      
      <p>
	The <code>Folio</code> object also provides the method for
	building a cross-reference table. The cross-reference table is
	represented by the <code>Xref</code> object. By default, a
	complete <code>Xref</code> object table is built with
	the <code>getxref</code> folio method. Such method, scan all
	cells in the folio and add them in the cross-reference table if
	the cell has a name.
      </p>

      <example>
	# get a default xref table 
	const xref (folio:getxref)
      </example>

      <p>
	The cross-reference table can also be built by searching for
	sheet tags. With a string argument, the <code>getxref</code>
	search for all sheets that matches the tag and then build a
	cross-reference table. This method is equivalent to the
	operation of building a new folio by tag with
	the <code>filter</code> method and then building the
	cross-reference table.
      </p>

      <example>
	# get a xref table by tag
	const xref (folio:getxref "the tag")
	# another method
	const sf   (folio:filter "the tag")
	const xref (sf:getxref)
      </example>

      <p>
	A cross-reference table can also be built by cell index and/or
	record index. With a cell index, the cross-reference table is
	built by indexing the sheet column. With both the cell and
	record indexes, the cross-reference table is built by indexing
	all cells at the coordinate for all sheets.
      </p>

      <example>
	# get a xref table by cell index
	const xref (folio:getxref 0)
	# get a xref table by cell and record index
	const xref (folio:getxref 0 1)
      </example>
    </subsect>
  </section>
</chapter>
