module Xlsxrb::Ooxml::Utils
OOXML-specific utility methods and constants.
Constants
- BUILTIN_DATE_FMT_IDS
-
Built-in numFmtIds that represent date/time formats.
- BUILTIN_NUM_FMT_CODES
-
Built-in number format codes defined by SpreadsheetML.
- DEFAULT_DATETIME_FORMAT
-
Default date-time format code used by
Writerfor Time cells. - DEFAULT_DATE_FORMAT
-
Default date format code used by
Writerfor Date cells. - EPOCH_1900
-
Excel 1900 date system epoch.
Public Class Methods
Source
# File lib/xlsxrb/ooxml/utils.rb, line 57 def date_to_serial(date) serial = (date - EPOCH_1900).to_i # Lotus 1-2-3 bug: serial 60 = Feb 29, 1900 (doesn't exist). # Dates on or after Mar 1, 1900 (raw serial >= 60) need +1. serial += 1 if serial >= 60 serial end
Converts a Date to an Excel serial number (1900 system).
Source
# File lib/xlsxrb/ooxml/utils.rb, line 73 def datetime_to_serial(time) date = time.to_date day_serial = date_to_serial(date) # Fractional part: seconds since midnight / seconds per day seconds_since_midnight = (time.hour * 3600) + (time.min * 60) + time.sec day_serial + (seconds_since_midnight.to_f / 86_400) end
Converts a Time to a fractional Excel serial number (1900 system).
# File lib/xlsxrb/ooxml/utils.rb, line 96 def hash_password(password, algorithm: "SHA-512", salt: nil, spin_count: 100_000) raise ArgumentError, "password must be a String" unless password.is_a?(String) raise ArgumentError, "spin_count must be a positive Integer" unless spin_count.is_a?(Integer) && spin_count.positive? salt_bytes = (salt || SecureRandom.random_bytes(16)).b # OOXML sheet/workbook protection hashing uses UTF-16LE password bytes. password_bytes = password.encode("UTF-16LE").b digest_name = algorithm.tr("-", "") hash = OpenSSL::Digest.digest(digest_name, salt_bytes + password_bytes) spin_count.times do |i| iteration_bytes = [i].pack("V") # little-endian uint32 hash = OpenSSL::Digest.digest(digest_name, hash + iteration_bytes) end { algorithm_name: algorithm, hash_value: [hash].pack("m0"), salt_value: [salt_bytes].pack("m0"), spin_count: spin_count } end
Hashes a plain-text password for use with sheet/workbook protection. Returns { algorithm_name:, hash_value:, salt_value:, spin_count: }. Algorithm per ECMA-376 Part 4 ยง2.4.2.24.
Source
# File lib/xlsxrb/ooxml/utils.rb, line 66 def serial_to_date(serial) # Adjust for Lotus 1-2-3 bug. serial -= 1 if serial > 60 EPOCH_1900 + serial end
Converts an Excel serial number (1900 system) to a Date.
Source
# File lib/xlsxrb/ooxml/utils.rb, line 82 def serial_to_datetime(serial) int_part = serial.to_i frac = serial - int_part date = serial_to_date(int_part) total_seconds = (frac * 86_400).round hours = total_seconds / 3600 minutes = (total_seconds % 3600) / 60 seconds = total_seconds % 60 Time.utc(date.year, date.month, date.day, hours, minutes, seconds) end
Converts a fractional Excel serial number to a Time (1900 system, UTC).