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]) |