Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How I can group by shapes with PptxGenJS? #307

Open
sensone opened this issue Mar 13, 2018 · 23 comments
Open

How I can group by shapes with PptxGenJS? #307

sensone opened this issue Mar 13, 2018 · 23 comments
Assignees
Milestone

Comments

@sensone
Copy link

sensone commented Mar 13, 2018

Hello. Could you help me?
Maybe you know Can I group 2 shapes with PptxGenJS?

Thanks a lot.
Have a good day.

@gitbrent
Copy link
Owner

Hi @sensone,

That feature does not exist as of yet.

@paulmjarosch
Copy link

This is a planned future feature?

@hirenj
Copy link

hirenj commented Sep 24, 2019

I've been digging around how to implement a few features in PptxGenJS. One thing I'd like to do is group shapes. Underneath the root p:spTree element in the slide XML, there are two child elements: p:nvGrpSpPr and p:grpSpPr (each with their own child elements). Following that is a bunch of p:Sp elements that contain the actual shapes / other elements.

To implement a group, I think it's as "simple" as creating a p:grpSp as a child of the p:spTree element, adding the group properties (i.e. p:nvGrpSpPr and p:grpSpPr), and then adding child p:Sp elements.

There are two tricky things to this though:

  1. If you don't calculate the bounding box of the child elements correctly, PowerPoint will draw the boundary for the group in the default location (i.e. top left corner)
  2. To do this properly, it would make sense to treat the slide as a special case of a group, and then move the xml generation for the slide objects into a method for a group.

I'm actually hacking away at this right now, but it's going to require refactoring that XML generation code. Before I get too deeply into this, what do you think @gitbrent ? I think the wacky bounding box for a group is something that can be lived with, but the refactoring could be quite fragile?

The api could work something like

let mygroup = slide.addGroup()
mygroup.addShape(...)
mygroup.addText(...)

slide.data.length == 1
mygroup.data.length == 2

@gitbrent
Copy link
Owner

Hi @hirenj

Thanks for the analysis. I have not researched grouping enough to understand what was required for a grouping API.

Is calculating a bounding box the only way to create groups? That sounds really cumbersome.

If you can come up with a group API that would be a great contribution, so I appreciate your time working on this.

  • Be sure to check the OOXML shape spec
  • Be sure you're working with the version-3.0 branch which is typescript and is much easier to patch (it'll be out soon)

@hirenj
Copy link

hirenj commented Sep 25, 2019 via email

@hirenj
Copy link

hirenj commented Sep 25, 2019

Hi,
I've done the decomposition for the XML generation into seperate files too - all of this is sitting in the groups branch of my fork. I'm going to hold off on doing any more changes for now until this gets tested on to make sure that I haven't introduced any regressions.

At least for the most basic use case, it looks like it works pretty nicely (with the proviso that the bounding box for the groups is completely off).

var PptxGenJS = require('./src/bld/pptxgen.cjs');

var pptx = new PptxGenJS();
var slide = pptx.addNewSlide();
var group = slide.addGroup();
group.addText('Hello World!', { x:1.5, y:1.5, fontSize:18, color:'363636' });
group.addText('Hello World!', { x:2.5, y:1.5, fontSize:18, color:'FF3636' });
group.addShape(pptx.shapes.LINE,      { x:4.15, y:4.40, w:5, h:0, line:'FF0000', lineSize:1 });
slide.addShape(pptx.shapes.LINE,      { x:1, y:4.40, w:5, h:0, line:'FFFF00', lineSize:1 });

pptx.writeFile('Sample Presentation').then( done => console.log(done) );

I think the code re-factoring that I did was a necessary step so that the types of objects that can be added in can be cleanly scaled up. The structure opens the door for things like centralising id generation for objects and adding new shape types (e.g. arbitrary polygons!). The first of those things is a prerequisite for tackling the big thing I'd like to put in - rudimentary animation support.

@TomD-JourneyOne
Copy link

Hey @hirenj , do you think you'll continue to work on your branch, or do you have any information about when / if it could potentially be merged into master?

@hirenj
Copy link

hirenj commented Feb 10, 2020

I've just taken a quick look at merging the changes in from the branch into master. Unfortunately it's not a clean merge (which I expected as it's mucking around with internals). I don't have the time right now to merge it in, although I do have a pretty good idea of what tasks need to be done to realise the merge (since the pptx stuff is already figured out). I can come back to this in maybe a month or two? Or I'm happy for someone else to implement this directly upon master if you want to discuss the design / approach in this thread?

@gitbrent
Copy link
Owner

Any help landing this feature would be appreciated.

@SandeepPamujula
Copy link

Hi @hirenj, @gitbrent, We are looking for grouping feature. Could you please let us know the way forward?

@hirenj
Copy link

hirenj commented Jul 24, 2020

I'm afraid I haven't had the time to do anything with this - but would some documentation as to what I was trying to achieve help at all? I'd imagine that my changes will be very much out of sync with the current codebase now, and it'll be easier to implement it from scratch again?

@pixelspark
Copy link

Hi all, any progress since the summer? Seems like a lot has been figured out already.. not sure if I am able to contribute (don't know the codebase at all..) but I would be able to provide feedback or have a look at any changes. Is https://github.com/hirenj/PptxGenJS/commits/groups still the most recent branch?

One thing to note is that in PowerPoint you can set rotation for a group and it rotates the items in the group (but all together, not individually). Might be something to keep in mind. As far as I can see there are no other things to be configured for a group (other than position and size obviously).

@gitbrent
Copy link
Owner

gitbrent commented Dec 7, 2020

The addition of grouping functionality requires quite a bit of plumbing on the back-end that has not been designed or developed.

@hirenj
Copy link

hirenj commented Dec 7, 2020 via email

@lukevella
Copy link

lukevella commented Mar 25, 2021

Hi, I also need this functionality and I have a working POC here: groups branch in lukevella/PptxGenJs. The API is based on what @hirenj suggested.

Example Usage

const group = slide.addGroup()
group.addText("Hello", { x: 1, y: 1, w: 3, h: 1 })
group.addText("World", { x: 2, y: 2, w:3, h: 1 })

The main change that allows this to happen is that I updated the parameters for functions that generate object definitions so that the target and slide are separate parameters. target is now a type Container which is an object that holds a list of slide objects – in this case it can be either a Slide or a Group.

- export function addTextDefinition(target: PresSlide, text: TextProps[], opts: TextPropsOptions, isPlaceholder: boolean) {
+ export function addTextDefinition(target: Container, slide: PresSlide, text: TextProps[], opts: TextPropsOptions, isPlaceholder: boolean) {

The other change is splitting the xml generation function so that we can recursively generate XML for grouped slide objects. For this I created slideItemObjsToXml(). Besides generating XML for a list of slide objects this function also returns position and size values that can contain the slide objects in the list. This is needed when creating groups since the position and size of the group object is based on its contents.

There's still some work to be done to get this ready but if @gitbrent is interested in this approach I'm happy to polish this up a bit further and publish a PR.

@lukevella lukevella mentioned this issue Mar 25, 2021
2 tasks
@ishantmehta012
Copy link

Hey @lukevella
Thanks for adding group functionality.
Do you have any timeline on when we can merge this PR to master. I am waiting for this feature.
cc: @gitbrent

@lukevella
Copy link

@ishantmehta012 I'm just waiting for feedback from @gitbrent. If he's happy with this direction I'm happy to help get this ready.

@hirenj
Copy link

hirenj commented Apr 22, 2021

@lukevella This looks like a great implementation! Glad to see that someone picked this up.

@TomD-JourneyOne
Copy link

@gitbrent @lukevella Are either of you guys still planning on merging in #929 ?

@marcog83
Copy link

Hi, first of all, thanks for the great library. PPTXGenJS is the de-facto standard to generate a PPTX in JS. AWESOME Job.
Group would be a good piece of functionality nice to have. Are you planning to merge it?
I'm working on a React renderer based on Yoga Layout, (something like react-pdf but for pptx) and Grouping is something i'm interested in.
Thanks

@gitbrent
Copy link
Owner

gitbrent commented Mar 1, 2022

Thanks @marcog83 !

The ability to group objects will be in Version 4.0. You can keep track of the feature via the Discussions tab.

@marcog83
Copy link

marcog83 commented Mar 12, 2022

@gitbrent thanks a lot for the feedback, it is actually a great news.
as I said I'm working on a react renderer you can find here...
https://github.com/marcog83/pptx-renderer
it is still a POC. i wish I could make it as stable as possible and share it with the community

@gitbrent gitbrent added this to the 4.0.0 milestone Mar 20, 2022
@gitbrent gitbrent self-assigned this Mar 20, 2022
@BioJeremy
Copy link

Is there any timeline for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.