forked from sheetjs/docs.sheetjs.com
		
	
		
			
				
	
	
		
			103 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			103 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
#!/usr/bin/env python3
 | 
						|
 | 
						|
lib = "libduktape.207.20700.so"
 | 
						|
 | 
						|
from ctypes import CDLL, byref, string_at, c_int, c_void_p, c_char_p, c_size_t
 | 
						|
 | 
						|
duk = CDLL(lib)
 | 
						|
 | 
						|
def str_to_c(s):
 | 
						|
  b = s.encode("utf8")
 | 
						|
  return [c_char_p(b), len(b)]
 | 
						|
 | 
						|
def duk_create_heap_default():
 | 
						|
  duk.duk_create_heap.restype = c_void_p
 | 
						|
  return duk.duk_create_heap(None, None, None, None, None)
 | 
						|
 | 
						|
def duk_eval_string_noresult(ctx, cmd):
 | 
						|
  [s, l] = str_to_c(cmd)
 | 
						|
  return duk.duk_eval_raw(ctx, s, l, 1 | (1<<3) | (1<<9) | (1<<10) | (1<<8) | (1<<11) )
 | 
						|
 | 
						|
def duk_eval_string(ctx, cmd):
 | 
						|
  [s, l] = str_to_c(cmd)
 | 
						|
  return duk.duk_eval_raw(ctx, s, l, 0 | (1<<3) | (1<<9) | (1<<10) | (1<<11) )
 | 
						|
 | 
						|
def duk_peval(ctx):
 | 
						|
  return duk.duk_eval_raw(ctx, None, 0, 1 | (1<<3) | (1<<7) | (1<<11) )
 | 
						|
 | 
						|
def duk_get_string(ctx, idx):
 | 
						|
  duk.duk_get_string.restype = c_char_p
 | 
						|
  retval = duk.duk_get_string(ctx, idx)
 | 
						|
  return retval.decode("utf8")
 | 
						|
 | 
						|
def eval_file(ctx, path):
 | 
						|
  with open(path, "r") as f:
 | 
						|
    code = f.read()
 | 
						|
    [s, l] = str_to_c(code)
 | 
						|
 | 
						|
    duk.duk_push_lstring(ctx, s, l)
 | 
						|
    retval = duk_peval(ctx)
 | 
						|
    duk.duk_pop(ctx)
 | 
						|
    return retval
 | 
						|
 | 
						|
def load_file(ctx, path, var):
 | 
						|
  with open(path, "rb") as f:
 | 
						|
    data = f.read()
 | 
						|
  ptr = c_char_p(data)
 | 
						|
  duk.duk_push_buffer_raw(ctx, 0, 1 | 2)
 | 
						|
  duk.duk_config_buffer(ctx, -1, ptr, len(data))
 | 
						|
  duk.duk_put_global_string(ctx, str_to_c(var)[0])
 | 
						|
  return data
 | 
						|
 | 
						|
def save_file(ctx, path, var):
 | 
						|
  duk.duk_get_global_string(ctx, str_to_c(var)[0])
 | 
						|
  sz = c_size_t()
 | 
						|
  duk.duk_get_buffer_data.restype = c_void_p
 | 
						|
  buf = duk.duk_get_buffer_data(ctx, -1, byref(sz))
 | 
						|
  s = string_at(buf, sz.value)
 | 
						|
  with open(path, "wb") as f:
 | 
						|
    f.write(s)
 | 
						|
 | 
						|
def process(path):
 | 
						|
  # initialize
 | 
						|
  context = duk_create_heap_default()
 | 
						|
  ctx = c_void_p(context)
 | 
						|
 | 
						|
  def DOIT(cmd):
 | 
						|
    return duk_eval_string_noresult(ctx, cmd)
 | 
						|
 | 
						|
  # duktape does not expose a standard "global" by default
 | 
						|
  DOIT("var global = (function(){ return this; }).call(null);")
 | 
						|
 | 
						|
  # load library
 | 
						|
  eval_file(ctx, "shim.min.js")
 | 
						|
  eval_file(ctx, "xlsx.full.min.js")
 | 
						|
 | 
						|
  # get version string
 | 
						|
  duk_eval_string(ctx, "XLSX.version")
 | 
						|
  print("SheetJS Library Version %s" % (duk_get_string(ctx, -1)))
 | 
						|
  duk.duk_pop(ctx)
 | 
						|
 | 
						|
  # read file
 | 
						|
  # NOTE: data is captured here to avoid GC
 | 
						|
  data = load_file(ctx, path, "buf")
 | 
						|
  print("Loaded file %s" % (path))
 | 
						|
 | 
						|
  # parse workbook
 | 
						|
  DOIT("wb = XLSX.read(buf.slice(0, buf.length));")
 | 
						|
  DOIT("ws = wb.Sheets[wb.SheetNames[0]]")
 | 
						|
 | 
						|
  # print CSV
 | 
						|
  duk_eval_string(ctx, "XLSX.utils.sheet_to_csv(ws)")
 | 
						|
  print(duk_get_string(ctx, -1))
 | 
						|
  duk.duk_pop(ctx)
 | 
						|
 | 
						|
  DOIT("newbuf = (XLSX.write(wb, {type:'buffer', bookType:'xlsb'}));")
 | 
						|
  save_file(ctx, "sheetjsw.xlsb", "newbuf")
 | 
						|
 | 
						|
  duk.duk_destroy_heap(ctx)
 | 
						|
  return 0
 | 
						|
 | 
						|
if("__main__" == __name__):
 | 
						|
  from sys import argv
 | 
						|
  process(argv[1]) |