Skip to content
This repository has been archived by the owner on Jun 2, 2022. It is now read-only.

Basic image embedding and row height feature #3

Merged
merged 3 commits into from Dec 20, 2016

Conversation

stewartsims
Copy link

This is a copy of the pull request submitted here: SheetJS#509

This adds the ability to embed images in the Excel exports. It also adds the ability to specify row height.

Usage for image embedding:

workbook.Sheets['my-sheet']['!images'] = [
	{
		name: 'image1.jpg',
		data: image[0].base64,
		opts: { base64: true },
		position: {
			type: 'twoCellAnchor',
			attrs: { editAs: 'oneCell' },
			from: { col: 2, row : 2 },
			to: { col: 6, row: 5 }
		}
	},
	{
		name: 'image2.jpg',
		data: image[1].base64,
		opts: { base64: true },
		position: {
			type: 'twoCellAnchor',
			attrs: { editAs: 'oneCell' },
			from: { col: 2, row : 10 },
			to: { col: 6, row: 14 }
		}
	}
];

Usage for row height:

ws['!rows'] = [
    {hpx:275},
    {hpx:100},
    {hpx:100}
];

These are basic changes to add these features, and so could be further improved to offer more functionality / configuration. However the general approach seems a reasonable basis for this and has been tested and found to work well.

Credit to @mgreter and @paulish for the original code changes. My only changes were a few fixes for multiple images.

mgreter and others added 3 commits November 29, 2016 10:30
@tarwich tarwich merged commit 7fc1bf3 into tarwich:master Dec 20, 2016
@mgreter
Copy link

mgreter commented Dec 22, 2016

Thanks @tarwich. FWIW I thought I might add how I used this lib in my POC.
Basic request was to enter data and take pictures on mobile and store as excel.
With js-xlsx and this PR it was quite easy to do so!
It's not self contained but you should get the idea:

<!-- this is part of an angular2 template -->
<input type="file" accept="image/*" capture="camera" (change)="onPicChange(pic)" #pic />
// method is part of a class!
onPicChange(data: any) : void {
  var self = this;
  var reader  = new FileReader();
  reader.addEventListener("load", function () {

    var img = new Image();
    var canvas = document.createElement("canvas");
    var ctx = canvas.getContext("2d");

    img.onload = function()
    {
      var maxWidth = 300;
      var width = img.width;
      var height = img.height;
      if (width > maxWidth) {
        height *= maxWidth / width;
        width = maxWidth;
      }
      canvas.width = width;
      canvas.height = height;
      ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, width, height);
      self.picSrc = canvas.toDataURL("image/jpeg");
      self.picBlob = self.picSrc.split(',')[1];
    }

    img.src = reader.result;

  }, false);
  reader.readAsDataURL(data.files[0]);
}

Then it follow the example given initially:

workbook.Sheets['Order-' + id]['!images'] = [
  { name: 'image1.jpg',
    data: this.picBlob,
    opts: { base64: true },
    position: {
      type: 'twoCellAnchor',
      attrs: { editAs: 'oneCell' },
      from: { col: 2, row : 2 },
      to: { col: 6, row: 5 }
    }
   },

I also stored the image data in an offline storage in base64 (not efficient, but works).

HTH

@pytdata
Copy link

pytdata commented Jul 30, 2021

Hi, I have tested your code but my export omits the images embedded.

This is the table that generates the excel contents:

Property Details Property Description Area m2 Rate (GH¢) Assesed Value (GH¢) Photo Illustration
Property ID: WRTB031 C1 Proposed 2 storey Residential building
Name of PAP: Gabriel Sarpong Floor Mass concrete
Phone No: 0549179207 Wall Sandcrete block wall neither rendered nor painted
Age 46 Window Burglar proof
Sex: Male Door Security door
National ID Type: Voter ID Ceiling Soffit of Reinforced concrete
National ID No. 8971010824 Roof Reinforced concrete
Ownership Status: Owner Other Developments Accomplished works @40%
Impact: Demolition and Relocation
GPS Cordinates of Property: 'N05.29127 'W001.98396
Use: Residence
N/A N/A N/A N/A

JS File:

codecBase64=(url, callback)=>{
let xhr = new XMLHttpRequest()
xhr.onload = ()=>{
let reader = new FileReader()
reader.onloadend = ()=>{
callback(reader.result)
}
reader.readAsDataURL(xhr.response)
}
xhr.open('GET', url)
xhr.setRequestHeader('Access-Control-Allow-Origin', '*')
xhr.responseType = 'blob'
xhr.send()
}

let wopts = { bookType:'xlsx', bookSST:false, type:'array' }

let workbook = XLSX.utils.book_new()
let ws1 = XLSX.utils.table_to_sheet(document.getElementById('projects-table'))
XLSX.utils.book_append_sheet(workbook, ws1, "sheet1")

let blop_masg
codecBase64('http://localhost/valid/nmk.png', (b)=>{
    blob = b.split(',')[1];
    console.log(blob)
    blop_masg = blob
})

let wbout = XLSX.write(workbook, wopts)
workbook.Sheets['sheet1']['!images']= [
    {
        name: 'nmk.png',
        data: blop_masg,
        opts: { base64: true },
        position: {
            type: 'twoCellAnchor',
            attrs: { editAs: 'oneCell' },
            from: { col: 8, row : 2 },
            to: { col: 8, row: 4 }
        }
    }
]

saveAs(new Blob([wbout],{type:"application/octet-stream"}), "test.xlsx")

Kindly advice what am doing wrong here. Thank you

@tarwich
Copy link
Owner

tarwich commented Aug 2, 2021

@pytdata

I'm no longer maintaining this repo, so I don't know. I'm willing to give you a guess, though. Check your base64 and make sure it's valid. I don't know if the rest of the code works, but you can validate your base64 to know if that's where the issue is.

https://codebeautify.org/base64-to-image-converter

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
4 participants