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
Development

Successfully merging this pull request may close these issues.

4 participants