github.com/shakinm/xlsReader@v0.9.12/xls/record/format.go (about)

     1  package record
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"github.com/metakeule/fmtdate"
     7  	"github.com/shakinm/xlsReader/helpers"
     8  	"github.com/shakinm/xlsReader/xls/structure"
     9  	"strconv"
    10  	"strings"
    11  )
    12  
    13  //FORMAT: Number Format
    14  
    15  var FormatRecord = []byte{0x1E, 0x04} //(41Eh)
    16  
    17  /*
    18  The FORMAT record describes a number format in the workbook.
    19  All the FORMAT records should appear together in a BIFF file. The order of FORMAT
    20  records in an existing BIFF file should not be changed. It is possible to write custom
    21  number formats in a file, but they should be added at the end of the existing FORMAT
    22  records.
    23  
    24  Record Data
    25  Offset		Field Name		Size		Contents
    26  ------------------------------------------------
    27  4			ifmt			2			Format index code (for internal use only)
    28  6			cch				2			Length of the string
    29  7			grbit			1			Option Flags (described in Unicode Strings in BIFF8 section)
    30  8			rgb				var			Array of string characters
    31  
    32  Excel uses the ifmt structure to identify built-in formats when it reads a file that was
    33  created by a different localized version. For more information about built-in formats,
    34  see "XF".
    35  
    36  */
    37  
    38  type Format struct {
    39  	ifmt     [2]byte
    40  	cch      [2]byte
    41  	grbit    [1]byte
    42  	rgb      []byte
    43  	vers     []byte
    44  	stFormat structure.XLUnicodeRichExtendedString
    45  }
    46  
    47  func (r *Format) Read(stream []byte, vers []byte) {
    48  
    49  	r.vers = vers
    50  
    51  	if bytes.Compare(vers, FlagBIFF8) == 0 {
    52  		copy(r.ifmt[:], stream[0:2])
    53  		_ = r.stFormat.Read(stream[2:])
    54  	} else {
    55  		copy(r.ifmt[:], stream[:2])
    56  		copy(r.cch[:], stream[2:4])
    57  		r.rgb = make([]byte, helpers.BytesToUint16(r.cch[:]))
    58  		copy(r.rgb[:], stream[4:])
    59  	}
    60  
    61  }
    62  
    63  func (r *Format) String() string {
    64  
    65  	if bytes.Compare(r.vers, FlagBIFF8) == 0 {
    66  		return r.stFormat.String()
    67  	}
    68  	strLen := helpers.BytesToUint16(r.cch[:])
    69  	return strings.TrimSpace(string(decodeWindows1251(bytes.Trim(r.rgb[:int(strLen)], "\x00"))))
    70  
    71  }
    72  
    73  func (r *Format) GetIndex() int {
    74  	return int(helpers.BytesToUint16(r.ifmt[:]))
    75  }
    76  
    77  func (r *Format) GetFormatString(data structure.CellData) string {
    78  	if r.GetIndex() >= 164 {
    79  
    80  		if data.GetType() == "*record.LabelSSt" {
    81  			return data.GetString()
    82  		}
    83  		if data.GetType() == "*record.Label" {
    84  			return data.GetString()
    85  		}
    86  
    87  		if data.GetType() == "*record.FakeBlank" {
    88  			return data.GetString()
    89  		}
    90  
    91  		if data.GetType() == "*record.Blank" {
    92  			return data.GetString()
    93  		}
    94  
    95  		if data.GetType() == "*record.BoolErr" {
    96  			return data.GetString()
    97  		}
    98  
    99  		if data.GetType() == "*record.Number" || data.GetType() == "*record.Rk" {
   100  			if r.String() == "General" || r.String() == "@" {
   101  				return strconv.FormatFloat(data.GetFloat64(), 'f', -1, 64)
   102  			} else if strings.Contains(r.String(), "%") {
   103  				return fmt.Sprintf("%.2f", data.GetFloat64()*100) + "%"
   104  			} else if strings.Contains(r.String(), "#") || strings.Contains(r.String(), ".00") {
   105  				return fmt.Sprintf("%.2f", data.GetFloat64())
   106  			} else if strings.Contains(r.String(), "0") {
   107  				return fmt.Sprintf("%.f", data.GetFloat64())
   108  			} else {
   109  				t := helpers.TimeFromExcelTime(data.GetFloat64(), false)
   110  				dateFormat := strings.ReplaceAll(r.String(), "HH:MM:SS", "hh:mm:ss")
   111  				dateFormat = strings.ReplaceAll(dateFormat, "\\", "")
   112  				return fmtdate.Format(dateFormat, t)
   113  			}
   114  
   115  		}
   116  
   117  		return data.GetString()
   118  
   119  	} else {
   120  		if data.GetType() == "*record.Number" {
   121  			return strconv.FormatFloat(data.GetFloat64(), 'f', -1, 64)
   122  		}
   123  	}
   124  	return data.GetString()
   125  }