0

printing multi record reports?

I have 900 contacts in my Contacts table (this is Ninox online, BTW), each denoting a member of our non-profit. We have committees, each of which is ID'd by a yes/no fields in the Contact record. So a contact may be a member of 0-4 committees. I have created a dashboard with a View (table) for each of these committees, with a formula for each so the table lists its members. That's all working fine, but I can't figure out how to print a report for each committee, showing all of its members. I keep reading that printing is by record.

I also tried this by creating views across my Contacts table that shows the same thing, but I can't get that entire list of (for example) 10 contacts to print as a report, only as individual records.

I've searched the documentation and Nioxus videos and even used AI. Am I just unable to print a report like this with Ninox, or am I missing something?

13 replies

null
    • John_Halls
    • 7 days ago
    • Reported - view

    Hi Dave

    Ninox can't print lists from a view. If you use a script in a button to loop through the records in the view you can update a reference to the record you will be able to print that as your member list. My recommendation would be to create the report from the committee table showing its members as that already has the relationship in place.

    Regards John

    • Fred
    • 6 days ago
    • Reported - view

    Since you are using the cloud version (guessing public), you have access to dynamic printing. With dynamic printing and JSON, you can print almost anything you want from anywhere you want. As long as you are not using a Page. 😉

    You can check out this post to see what you can do with dynamic printing.

    To make that page in the post, I am in a parent table only so I can access the necessary data to create the JSON that Carbone uses to create the table. The code looks something like:

    {
        leagueNum: League,
        league: League.FullName,
        season: Year,
        success: "#ffc505",
        normal: "#000000",
        mlsjGreen: "#85FF00",
        teams: for loop1 in ActiveTeams do
            let recs := loop1.TeamEventSummary;
            {
                teamName: loop1.displayName,
                totals: sum(recs.Points),
                standing: last(recs[Location.'Start Date' < today()].CurrentStanding),
                e1P: first(recs['Event Order' = 1].Points),
                e1tPl: first(recs['Event Order' = 1].Placing),
                e1FR: first(recs['Event Order' = 1].FTPnts),
                e1tmPnt: first(recs['Event Order' = 1].TeamPnts) + first(recs['Event Order' = 1].FTPnts),
                e1qPl: first(recs['Event Order' = 1].IndividualRoundSum[Round = "Q"].Placing),
                e1qPnt: first(recs['Event Order' = 1].IndividualRoundSum[Round = "Q"].Points),
                e1gpPl: first(recs['Event Order' = 1].IndividualRoundSum[Round = "GP"].Placing),
                e1gpPnt: first(recs['Event Order' = 1].IndividualRoundSum[Round = "GP"].Points),
    etc....
    }

    I am in the parent record called Seasons. This parent record has no local data on the teams for the season only through links, so I'm creating a new "table" of records that is based around my teams at line 8.

    Also with dynamic printing you can create a button that creates the pdf, then saves it to another table for storage.

    It does mean learning yet another coding system, but if printing is important then I think it is worth while.

    • Dave_Airel
    • 5 days ago
    • Reported - view

    FYI I have it working after    and   's suggestions. Here's the thumbnail of what I did.

    In Contacts I added 7 yes/no (checkbox) fields, one for each committee.
    In my Working Group table, I created one record per committee with a simple text label field to identify if.
    I created a junction table to allow me to have a N:N relationship between Working Group and Contacts. I placed a reference field in the Working Group record.
    I placed a button in that same record to parse contacts & capture all committee members and their committees.
    The reference field on each record pulls the appropriate contacts from the junction table, and since it's a reference field, I can print it to PDF.

    What I'd really like is to have these PDFs created automatically (1/week maybe?) and pushed to a folder in our Google Drive. When I get some free time I'll explore the dynamic printing idea here. Thanks to you both -
     

    • Dave_Airel
    • 2 days ago
    • Reported - view

    I've been playing around with dynamic priting. Created a Word template (attached), loaded into Ninox (screenshot, the form prints fine but no data. Been poking around documentation and AI for awhile and I'm stumped. Can anyone point me a what I'm missing?

      • Fred
      • 2 days ago
      • Reported - view

       Good start. 

      1) Carbone does not like spaces, so d.Report Title and d.Report Created will not work.

      2) try removing the first two lines and adding a new table row and put this in the second line:

      {d.Committee_Membership[i+1]}

      See if that works. You need the second row with the [i+1] to tell Carbone to iterate through a reference field. You don't need anything else just the line.

      3) if that all works, now how to fix the first two lines without renaming them?

      a) you can create a formula fields called ReportTitle and ReportCreated and have that equal their respective fields, then reference the new fields in the template.

      b) you can flip the switch on Custom JSON and put:

      {
          ReportTitle: Report Title,
          ReportCreated: Report Created,
          CommitteeMembership: Committee_Membership.{
              FullName: Full_Name,
              Email: Email,
              etc
          }
      }

      then make modifications in the template so it references the JSON key value not the Ninox field names, e.g. ReportTitle, ReportCreated, CommitteeMembership, FullName, etc.

      The first one is easier in this case, but I would recommend you get use to JSON so you can create tables from data that is not stored in your database when you need to.

      • Dave_Airel
      • 2 days ago
      • Reported - view

       Thx for the guidance. I fixed the report title & date they are now fine. But the table keeps showing up blank.

      My Committee_Membership is a view (table) made up of records from a junction table called Committee_Membership (which in turn just references my Contacts table and a Committee table to allow me to match contacts up to their committees. This table winds up with every contact who belongs to a committee, and the name of that committee (contacts might belong to more than one committee).

       

      I cut my Word template down to two columns, Lastname and Firstname to test.

      When I try using JSON, I keep getting script errors saying it can't find the fields I'm specifying in my reference table.Here's a screenshot of the script editor as I'm entering the script. It can't find these fields.


      Could my N:N reference table be the issue?

      Also in the JSON tutorial I watched last night, it emphasized that JSON keys must be enclosed in "", and that a space must follow the key before the colon. Is the Ninox implementation different and can you point me at that documentation?

    • Fred
    • 2 days ago
    • Reported - view
     said:
    Could my N:N reference table be the issue?

     It is not your table that is the issue, but how you reference fields. Now with more information, you are not providing the proper path to the field names.

    I'm guessing that Firstname and Lastname are in the Member table, so you need to add Member to the . path.

    {d.Committee_Membership[i].Member.LastName}

    You will also need to do this in the JSON code.

    CommitteeMembership: Committee_Membership.{
        lastName: Member.Lastname
    }

    In normal JSON creation you do need to put the " " around the key, but in Ninox when you are telling it to create JSON you don't. Ninox will put them in for you. Take the same JSON formula and put it into a formula field and you will see the results properly formatted.

    • Fred
    • yesterday
    • Reported - view

    Remember to create a second row of your table and add:

    {d.Committee_Membership[i+1]}

    Otherwise Carbone won't iterate.

    You can checkout their documentation here. I have found them to be very helpful if you have a question.

      • Dave_Airel
      • yesterday
      • Reported - view

       Thanks - I'll definitely read over the documentation once I get past this first report - which is making what little hair I have left fall out.

      My Word doc looks right to me.Screenshot 2025-11-30 at 6.17.05AM

      My test print template matches the Word doc.Screenshot 2025-11-30 at 6.19.54AM

      My JSON script looks right and has no errors. Screenshot 2025-11-30 at 6.22.47AM

      And yet my report (while now printing the right number of rows) is still blank. (and the date format is being lost.report-IVVFUpFuGuKo9oVP

      It's probably something obvious but I'm not seeing it.

      Once I get this two-column test working I'll add in the other fields I need ...

      • Fred
      • yesterday
      • Reported - view

       Did you select Custom JSON? If so then you don't need:

      Committee_Membership.Member
      
      just
      
      Committee_Membership

      Plus your JSON only has Last Name and First Name.

      Just remember that if you use Custom JSON, then you have to follow the field names and path that you create there NOT what is Ninox.

      So you can try just turning off Custom JSON, unless of course you didn't change the field names in Ninox.

      A tip, to save typing the 2nd row of the Carbone code doesn't need to be exactly the same as the first line. You can just put:

      {d.Committee_Membership[i+1}}

      In the 2nd row first cell and Carbone will do the rest.

      • Dave_Airel
      • yesterday
      • Reported - view

       Aah. That worked. So I only need to use a JSON script if my DB field names aren't Carbone-friendly? Sorry for the barrage of questions, I will go through the Carbone docs and find a good JSON tutorial once I get this report finished.

    • Fred
    • 20 hrs ago
    • Reported - view
     said:
    So I only need to use a JSON script if my DB field names aren't Carbone-friendly?

     That is correct, or if you need to get data from different tables that are not linked, or need to create summary data that is not somewhere else.

    No worries about the questions. It is a new language to learn and we are all here to help.

    • Rafael Sanchis
    • Rafael_Sanchis
    • 4 hrs ago
    • Reported - view

    And example grouping data.

    The Code in a Button

    let vTbl := ((select 'Planning Data' where year('Date Start') = 2025) order by text('a_Employee Name'.'Employee Name'));

    let vObj := vTbl.{

    vDat: format('Date Start', "DD.MMM.YYYY"),

    vDat1: format('Date Finish', "DD.MMM.YYYY"),

    vPrice: format('Revenue Week', "€ #,##0.00"),

    vCatg: text('a_Employee Name'.'Employee Name'),

    vAcc: text('a_Project Name'.'Project Name'),

    vTxt: Discipline,

    vDatArr: let xDat := 'a_Employee Name'.'Employee Name';

    vTbl['a_Employee Name'.'Employee Name' = xDat].'a_Employee Name'.'Employee Name',

    vSum: let yDat := 'a_Employee Name'.'Employee Name';

    format(sum(vTbl['a_Employee Name'.'Employee Name' = yDat].'Revenue Week'), "€ #,##0.00"),

    vTGst: format(sum((select 'Planning Data' where 'Date Start' and year('Date Start') = 2025).'Revenue Week'), "€ #,##0.00")

    };

    let xArr := [{}][null];

    let xObj := {};

    for i from 0 to cnt(vObj) do

    xObj := item(vObj, number(i));

    if i = 0 then

    setItem(xObj, "vSkip", 1);

    if item(vObj, number(i)).text(vDatArr) != item(vObj, number(i + 1)).text(vDatArr) then

    setItem(xObj, "vSkipSum", 3)

    end;

    xArr := array(xArr, [xObj])

    else

    if item(vObj, number(i - 1)).text(vDatArr) = item(vObj, number(i)).text(vDatArr) then

    setItem(xObj, "vSkip", 0);

    if item(vObj, number(i)).text(vDatArr) != item(vObj, number(i + 1)).text(vDatArr) then

    setItem(xObj, "vSkipSum", 3)

    end;

    xArr := array(xArr, [xObj])

    else

    setItem(xObj, "vSkip", 1);

    if item(vObj, number(i)).text(vDatArr) != item(vObj, number(i + 1)).text(vDatArr) then

    setItem(xObj, "vSkipSum", 3)

    end;

    xArr := array(xArr, [xObj])

    end

    end

    end;

    let pJson := {

    pName: "Modify by Rafael Sanchis",

    pYear: "2025/2026",

    pTbl: xArr

    };

    Report := importFile(this, printAndSaveRecord(this, "Group2", pJson), "PrintOut.pdf");

    alert(" ✅ Proceso finalizado archivo generado en PDF.")

Content aside

  • 4 hrs agoLast active
  • 13Replies
  • 72Views
  • 4 Following