• Don Pierce
  • NEWBIE
  • 50 Points
  • Member since 2017

  • Chatter
    Feed
  • 0
    Best Answers
  • 0
    Likes Received
  • 0
    Likes Given
  • 7
    Questions
  • 10
    Replies
I would assume the code below should work but I seem to have my syntax wrong. I guess I need to ask is this legal.  Trying to implement an If/else if logic.


  <apex:image width="180" height="40" id="theImage3" value="{!IF(LEFT(relatedTo.rstk__Buyer_Contact__c,3)='Lee',  
"https://geometricsinc123456--rspilot--c.cs97.content.force.com/servlet/servlet.FileDownload?file=0150U00000052qp","{!IF(LEFT(relatedTo.rstk__Buyer_Contact__c,3)='barb',"https://geometricsinc123456--rspilot--c.cs97.content.force.com/servlet/servlet.FileDownload?file=0150U00000050cW",""))}}"></apex:image>
 
I have setup an email template to handle headers and footers. The problem I have is the content inbetween will not align properly.  I get an error when I try to use a div around the middle content and this appears to be due to the use of the apex:repeat code. I think it has to do with the css settings but have not been able to resolve.
Here is the code and I have attached the PDF rendered.  I have a few extra lines in there as I have been testing.
<messaging:emailTemplate subject="Sales Order Invoice Geo" recipientType="User" relatedToType="rstk__FSOINVH__c">
<messaging:htmlEmailBody >
<html>
<head>
<style>
    @page {
     size:a4;
     margin-left: 1.3cm;
     margin-right: 0.4cm;
     margin-top: 8.0cm;
     margin-bottom: 4.5cm;

     @top-left {
           content: element(header);
       }
     @bottom-left {
           content: element(footer);
       }
}
     div.header {
                display: block;
                padding: 1px;
                position: running(header);
                padding-top: 1.0cm;
      }
     div.footer {
                display: block;
                padding: 1px;
                position: running(footer);
      }
    body, table, th, td, div { 
        font:normal normal 95%/1.0 arial, times new roman, verdana; 
    }
    body {
        counter-reset: pg -1;
    }
    table {
        cell-padding: 0;
        cell-spacing: 0;
    }
    #main {

        width:690px;
        background:#ffffff;
    }
    #cont {
        display:block;
        }
    .headerSect {
        width:700px;
    }
    .logoDiv {
        height:56px;
        width:220px;
    }
    .logoDiv img {
        display: block;
        height: 100%;
    }
    .cmpLogo {
        max-height:66px;
        max-width:250px;
    }
    .header2 {
        width:400px;
        border: 1px solid;
        padding: 1px;
    }
    .formTitle {
        float:left;
        font-weight: bold;
        font-size: 140%;
        padding-left:4px;
    }
    .pageNumSect {
        float:right;
        counter-increment: pg;
    }
    div.pageNumSect:before {
        content: "Page " counter(pg) " of " ;
    
    }
    .headerInfo {
        margin-top:24px;
        padding: 2px;
    }
    .hdrInfoLbl {
        font-weight: bold;
    }
    .hdrInfoData {
        font-weight: normal;
    }
    td {
        padding: 2px;
    }
    .addressSect {
        background-color: #000000;
        width:700px;
        margin-top:6px;
        margin-right:2px;
    }
    .addressSect th {
        text-align:center;
        font-weight: bold;
        background-color:#000000;
        color:#ffffff;
        padding: 2px;
    } 
    .addressSect td {
        background-color:#ffffff;
    } 
    .termsSect {
        width:700px;
        margin-top:6px;
        border: 1px solid;
    }
    .termsSect td {
        vertical-align:top;
    }
    .termsSect td:nth-child(1) {
        width: 17%;
        font-weight: bold;
    }
    .termsSect td:nth-child(2) {
        width: 33%;
    }
    .termsSect td:nth-child(3) {
        width: 15%;
        font-weight: bold;
    }
    .termsSect td:nth-child(4) {
        width: 35%;
    }
    table.lines {
        width:700px;
        table-layout:fixed;
        background-color: #ffffff;
        margin-top:6px;
        border-top: 1px solid;
        border-bottom: 1px solid;
        border-right: 1px solid;
        margin-left: auto;
        margin-right:auto;

    }
    table.lines td {
        background-color:#ffffff;
        vertical-align:top;
        padding: 1px;
        border-left: 1px solid black;
    }
    table.lines th {
        background-color:#000000;
        color:#ffffff;
        padding: 0px 0px 0px 0px;
        text-align:center;
        font-weight:bold;
    }
    table.footerSect {
        width:700px;
        margin-top:6px;
        margin-right:2px;
        border-top: 1px solid;
        border-bottom: 1px solid;
        border-right: 1px solid;
    }
    table.footerSect td {
        margin-top: 6px;
        border-left: 1px solid black;
    }
    table.footerSect td td {
        border: none;
    }
    //230
    .totalLabel {
        font-weight: bold;
        width: 90px;
    }
    .totalAmt {
        text-align:right;
        width: 140px;
    }
    .totalSect td {
        border: 0;
    }
    .shippingComments {
        font-weight:bold;
    }
    table.lines tr.lines_content_row td.col_description {
        text-align:left;
        font-weight:bold;
        text-overflow:ellipsis;
        padding-left: 1em;
        white-space: wrap;
        font-size:8pt;
        color:blue;
    }
    table.lines tr.lines_content_row td.col_comment {
        text-align:left;
        font-style:italic;
        padding-left: 1em;
        text-overflow:ellipsis;
    }
    table.lines tr.lines_content_row td.col_empty {
        text-align:left;
        color: #ffffff;
    }
    table.lines tr.lines_content_row td.col_serial {
        text-align:left;
        padding-left: 1em;
        text-overflow:ellipsis;
    }
    table.lines tr.lines_content_row td.col_component {
        text-align:left;
        padding-left:1em;
        text-overflow:ellipsis;
    }
    table.lines tr.lines_content_row td.col_product{
        text-align:left;
        text-overflow:ellipsis;
    }
    table.lines tr.lines_content_row td.col_uom {
        text-align:center;
        font-size:8pt;
    }
    table.lines tr.lines_content_row td.col_shipper {
        text-align:center;
    }
    table.lines tr.lines_content_row td.col_tax {
        text-align:center;
    }
    table.lines tr.lines_content_row td {
        text-align:right; 
        overflow:hidden;
        text-overflow:clip;
        white-space:nowrap;
    }
    table.lines {
        padding-bottom: {!38 - relatedTo.rstk__numLines__c}em;
    }
    .wrapper{position:relative;}
    .right,.left{width:50%; position:absolute;}
    .right{right:0;}
    .left{left:0;}

</style>
</head>
<body>
<div id="main">
<!--apex:repeat value="{pages}" var="page"-->
  <div class="header">
    <div class="headerSect">
      <table cellspacing="0" cellpadding="0" border="1">
      <tr><td valign="middle" width="300px">
        <div class="logoDiv">
<!--             <apex:image height="48px"  width="204px" value="{!relatedTo.rstk__companylogo__c}" rendered="{!!ISBLANK(relatedTo.rstk__companylogo__c)}"/>-->
           <apex:image styleClass=".cmpLogo" value="{!relatedTo.rstk__companylogo__c}" rendered="{!!ISBLANK(relatedTo.rstk__companylogo__c)}"/> 
       </div>
      </td><td  width="400px">
 <!--       <div class="header2">-->
            <div class="formTitle">Sales Invoice</div>
           <div class="pageNumSect">{!relatedTo.rstk__pages__c}</div>

             <apex:panelGrid styleClass="headerInfo" columnClasses="hdrInfoLbl,hdrInfoData" columns="2" width="100%">
                <apex:outputText value="Invoice Number"/>
                <apex:outputText value="{!relatedTo.rstk__invoiceno__c}"/>
                <apex:outputText value="Invoice Date"/>
                <apex:outputText value="{0,date,short}">
                  <apex:param value="{!relatedTo.rstk__invdate__c}"/>
                </apex:outputText>
                <apex:outputText value="Sales Order Number"/>
                <apex:outputText value="{!relatedTo.rstk__order__c}"/>
                <apex:outputText value="Customer PO Number"/>
                <apex:outputText value="{!relatedTo.rstk__custpo__c}"/>
            </apex:panelGrid>
   <!--     </div> -->
      </td></tr></table>
    </div>
        <table  border="0" cellspacing="0" cellpadding="0" class="lines" style="float:left">
        <tr class="lines_header_row">
          <th width="4%" >Line</th>
          <th width="44%">Product</th>
          <th width="4%" >UOM</th>
          <th width="12%">Shipper</th>
          <th width="7%" >Quantity</th>
          <th width="9%" >Unit Price</th>
          <th width="7%" >Discount</th>
          <th width="10%">Extension</th>
          <th width="3%" >Tax</th>
        </tr></table>

  </div>
  <div class="footer">
    <table class="footerSect" cellpadding="5" cellspacing="0" border="1">
     <tr><td>
      <apex:outputText value="These items are controlled by the U.S. Government and authorized for export only to the country of ultimate destination for use by the ultimate consignee or end-user(s) herein identified. They may not be resold, transferred, or otherwise disposed of, to any other country or to any person other than the authorized ultimate consignee or end-user(s), either in their original form or after being incorporated into other items, without first obtaining approval from the U. S. government or as otherwise authorized by the U. S. law and regulations."/>
     </td></tr>
    </table>
 
  </div>
   <table  border="0" cellspacing="0" cellpadding="0" class="lines"  style="float:left">
      <tr>
          <th width="4%" >Line</th>
          <th width="44%">Product</th>
          <th width="4%" >UOM</th>
          <th width="12%">Shipper</th>
          <th width="7%" >Quantity</th>
          <th width="9%" >Unit Price</th>
          <th width="7%" >Discount</th>
          <th width="10%">Extension</th>
          <th width="3%" >Tax</th>
        </tr>
        <apex:repeat var="l" value="{!relatedTo.rstk__lines__r}">
        <tr class="lines_content_row">
            <apex:variable var="isSpanRow" value="{!l.rstk__linetype__c='Description'}" />
            <!-- Description Panel - Spans Across Table -->
            <apex:outputPanel layout="none" rendered="{! isSpanRow }">
                <!-- Blank Line Number Column -->
                <td></td> 
                <!-- Description Column -->
                <td class="col_description" colspan="8" >{!l.rstk__comment__c}</td> 
            </apex:outputPanel>
            <!-- Standard Panel - No Spans -->
            <apex:outputPanel layout="none" rendered="{! !isSpanRow }">
                <!-- Line Number Column -->
                <td class="col_lineno">{!l.rstk__invline__c}</td>
                <!-- Product Column -->
                <apex:variable var="productClass" value="{! 'col_product' + IF(l.rstk__linetype__c='Empty',' col_empty','') + IF(l.rstk__linetype__c='Detail', '', '') + IF(l.rstk__linetype__c='Prepayment','','') + IF(l.rstk__linetype__c='PrepaymentApplied','','') + IF(l.rstk__linetype__c='Comment',' col_comment', '') + IF(l.rstk__linetype__c='Serial', ' col_serial', '') + IF(l.rstk__linetype__c='Component', ' col_component', '') }"/>
                <apex:variable var="productDisplayVal" value="{! '' + IF(l.rstk__linetype__c='Empty', 'X', '') + IF(l.rstk__linetype__c='Detail', l.rstk__prod__c, '') + IF(OR(l.rstk__linetype__c='Prepayment', l.rstk__linetype__c='PrepaymentApplied', l.rstk__linetype__c='Comment', l.rstk__linetype__c='Serial'), l.rstk__comment__c, '') + IF(l.rstk__linetype__c='Component', l.rstk__component__c , '') }"/>
                <td class="{!productClass}">
                    {!productDisplayVal}
                </td>
                <!-- Unit Of Measure Column -->
                <td class="col_uom">{!l.rstk__uom__c}</td>
                <!-- Shipper Column -->
                <td class="col_shipper">{!l.rstk__shipper__c}</td>
                <!-- Quantity Column -->
                <td class="col_qty">
                    <apex:outputText value="{0,Number,###,###,###,##0.00}" rendered="{!OR(l.rstk__linetype__c='Detail',l.rstk__linetype__c='Prepayment')}">
                        <apex:param value="{!l.rstk__qty__c}"/>
                    </apex:outputText>
                </td>
                <!-- Unit Price Column -->
                <td class="col_unitprice">
                    <apex:outputText value="{0,Number,###,###,###,##0.00}" rendered="{!l.rstk__linetype__c='Detail'}">
                        <apex:param value="{!l.rstk__price__c}"/>
                    </apex:outputText>
                    <apex:outputText value="{0,Number,###,###,###,##0.00}" rendered="{!l.rstk__linetype__c='Component'}">
                        <apex:param value="{!l.rstk__unitprice__c}"/>
                    </apex:outputText>
                </td>
                <!-- Discount Column -->
                <td class="col_discount">
                    <apex:outputText value="{0,Number,###,###,###,##0.00}%" rendered="{!!ISBLANK(l.rstk__discpct__c)}">
                        <apex:param value="{!l.rstk__discpct__c}"/>
                    </apex:outputText>
                </td>
                <!-- Extension Column -->
                <td class="col_extension">
                    <apex:variable var="isPrepaymentApplied" value="{! l.rstk__linetype__c='PrepaymentApplied' }"/>
                    <apex:variable var="extensionAmount" value="{! IF(isPrepaymentApplied, (l.rstk__price__c - l.rstk__discamt__c) * l.rstk__qty__c , (l.rstk__price__c - l.rstk__discamt__c) * l.rstk__qty__c )}"/>
                    <apex:outputText value="{0,Number,###,###,###,##0.00}">
                        <apex:param value="{!extensionAmount}"/>
                    </apex:outputText>
                </td>
                <!-- Tax Column -->
                 <td class="col_tax">
                     <apex:outputText value="{!IF(OR(relatedTo.rstk__taxexempt__c, l.rstk__taxexempt__c),'','Y')}" rendered="{!!ISBLANK(l.rstk__invline__c)}"/>
                 </td>
            </apex:outputPanel>
        </tr>
        </apex:repeat>
    </table>

<!--/apex:repeat-->
  <table  cellpadding="0" cellspacing="0" border="1" width="100%" style="float:left">
    <tr><td width="460px" valign="top">
      <div style="overflow:hidden;max-height:85px;"><apex:outputText escape="false"  value="{!relatedTo.rstk__extcomment__c}"/></div>
      </td>
      <td width="240px">
      <apex:panelGrid styleClass="totalSect" columnClasses="totalLabel,totalAmt" columns="2" width="240px" >
        <apex:outputText value="SubTotal"/>
        <apex:outputText value="{0,Number,###,###,###,###,##0.00}">
            <apex:param value="{!relatedTo.rstk__total__c}"/>
        </apex:outputText>
        <apex:outputText value="Discount" rendered="{!AND(!ISNULL(relatedTo.rstk__discamt__c), relatedTo.rstk__discamt__c>0)}"/>
        <apex:outputText value="({0,Number,###,###,###,###,##0.00})" rendered="{!AND(!ISNULL(relatedTo.rstk__discamt__c), relatedTo.rstk__discamt__c>0)}">
            <apex:param value="{!relatedTo.rstk__discamt__c}"/>
        </apex:outputText>
        <apex:outputText value="Shipping"/>
        <apex:outputText value="{0,Number,###,###,###,###,##0.00}">
            <apex:param value="{!relatedTo.rstk__freightamt__c+relatedTo.rstk__handlingamt__c+relatedTo.rstk__packageamt__c}"/>
        </apex:outputText>
        <apex:outputText value="Tax"/>
        <apex:outputText value="{0,Number,###,###,###,###,##0.00}">
            <apex:param value="{!relatedTo.rstk__taxamt__c}"/>
        </apex:outputText>
        <apex:outputText value="Prepayment"/>
        <apex:outputText value="({0,Number,###,###,###,###,##0.00})">
            <apex:param value="{!relatedTo.rstk__totalppya__c}"/>
        </apex:outputText>
        <apex:outputText value="Invoice Total"/>
        <apex:outputText value="{0,Number,###,###,###,###,##0.00}">
            <apex:param value="{!relatedTo.rstk__grandtotal__c - relatedTo.rstk__totalppya__c}"/>
        </apex:outputText>
      </apex:panelGrid>
    </td></tr>
  </table>
</div>
</body>
</html>
</messaging:htmlEmailBody>
</messaging:emailTemplate>

 
I created a simple Apex Class and VFC to display my query results in an email template.
The only thing it displays is the correct size of the list and a blank POId . No List results.
*********************Apex Code
global class POComponent
{
global string POId
    {
    get;
    set;
    }
global integer leng
    {
    get;
    set;
    }
global List<rstk__poline__c> RSNPOLine2
    {
    get;
    set;
    }
public POComponent()
    {
    POComponentCore();
    }
public List<rstk__poline__c> POComponentCore()
    {
    POId = ApexPages.currentPage().getParameters().get('id');
    List<rstk__poline__c> RSNPOLine2  = new List<rstk__poline__c>();
    RSNPOLine2 = [SELECT rstk__poline_lne__c,rstk__poline_item__c, rstk__poline_descr__c FROM rstk__poline__c where rstk__poline_ordno__c = :POId];
     leng = RSNPOLine2.size();
    return RSNPOLine2;
    }
}
*************************VFC code:
<apex:component controller="POComponent" access="global">
<apex:attribute name="configproducts" description="DCPId" type="String" assignTo="{!POId}"/>
            <table>
            <apex:repeat var="arr" value="{!RSNPOLine2}">
                <tr>
                    <td style="width: 010mm;   height: 004mm;">Just a test inside VFC</td>
                    <td style="width: 025mm;   height: 004mm;">
                        <div style="width: 100%; max-width:100%; white-space: nowrap; overflow: hidden;">{!arr.rstk__poline_descr__c}</div>
                    </td>
                    <td style="width: 067mm; height: 004mm; ">
                        <div style="width: 100%; max-width:100%; white-space: nowrap; overflow: hidden;">{!arr.rstk__poline_item__c}</div>
                    </td>
                    <td style="width: 010mm;   height: 004mm;">
                        <div style="width: 100%; max-width:100%; white-space: nowrap; overflow: hidden; text-align: right;">{!arr.rstk__poline_lne__c}</div>
                    </td>
                    <td style="width: 010mm;   height: 004mm; ">
                        <div style="width: 100%; max-width:100%; white-space: nowrap; overflow: hidden; text-align: left; margin-left: 1mm;">CCCCC</div>
                    </td>
                    <td style="width: 025mm;   height: 004mm;">
                        <div style="width: 100%; max-width:100%; white-space: nowrap; overflow: hidden; text-align: right;">1111.99</div>
                    </td>
                </tr>
             </apex:repeat>
            </table>
                <table>
                <tr><td>This is outside the repeat loop, list size = {!leng} and POId is {!POId}</td></tr></table>
</apex:component>
******************Email Template code:
<messaging:emailTemplate subject="Purchase Order" recipientType="User" relatedToType="rstk__PO_Print_Header__c">
<messaging:htmlEmailBody >
<html>
<head>
<style type="text/css" media="print">
 @page {
     size:A4;
     margin-left: 0.8cm;
     margin-right: 0.8cm;
     margin-top: 12.0cm;
     margin-bottom: 4.5cm;
     @top-center {
           content: element(header);
       }
     @bottom-left {
           content: element(footer);
       }
}
 </style>
 </head>
 <body>
        <c:POComponent configproducts="{!relatedTo.Id}"/>
</body>
</html>
</messaging:htmlEmailBody>
</messaging:emailTemplate>
I am trying to concatenate two fields and insert into a Note.
It works fine when I use text but fails when I try to use a textarea
InstrumentName__c is a text(255) field and IntrumentProblem_c is textarea(255)
The following works fine:

var repnew3 = new sforce.SObject('Note');
repnew3.ParentId = qr.records.Id;
repnew3.Title = '{!Case.Subject}';
// combine 
repnew3.Body = '{!Case.InstrumentName__c}';
result3 = sforce.connection.create([repnew3]);

 This will not work:

var repnew3 = new sforce.SObject('Note');
repnew3.ParentId = qr.records.Id;
repnew3.Title = '{!Case.Subject}';
// combine 
repnew3.Body = '{!Case.InstrumentProblem__c}';
result3 = sforce.connection.create([repnew3]);

Is there a conversion process require or does the Note.Body field not accept textarea?

Ultimately I want to concatenate the two as follows:
var repnew3 = new sforce.SObject('Note');
repnew3.ParentId = qr.records.Id;
repnew3.Title = '{!Case.Subject}';
// combine 
repnew3.Body = 'Problem: ' + '{!Case.InstrumentProblem__c}' + '  Name: ' + '{!Case.InstrumentName__c}';
result3 = sforce.connection.create([repnew3]);

This is being used as a button action on the Case layout.
The error returned upon a delete of a Quote Line Item is:

There were custom validation error(s) encountered while saving the affected record(s). The first validation error encountered was "Apex trigger QuoteLineItemTrigger caused an unexpected exception, contact your administrator: QuoteLineItemTrigger: execution of AfterDelete caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.QuoteLineItemTrigger: line 12, column 1". 

This is the code, I tried after delete and before delete. It works fine for after insert and after update.

trigger QuoteLineItemTrigger on QuoteLineItem (after insert, after update, after delete){  
    
    // prevent recursion
    if (!QuoteLineItemUtility.TriggerIsRunning){
        QuoteLineItemUtility.TriggerIsRunning = true;

        Set<Id> QuoteIds = new Set<Id>();
 
        List<QuoteLineItem> lineItemsForUpdate = new List<QuoteLineItem>();

        // gather IDs first of quotes
       for (QuoteLineItem ql : trigger.new) {   // line 12
            
                 QuoteIds.add(ql.QuoteId);
        }

        if (!QuoteIds.isEmpty()) {
            // get all line items for all of the above quotes in bulk so that we don't hit governor limits
            Id prevQuoteId;
            Double lastLineNumber;
            // we can query all and these triggered records in an after trigger, nothing missing
            for (QuoteLineItem ql : [Select Id, Item_Numbering__c,QuoteId,SortOrder
                                       From QuoteLineItem 
                                      Where QuoteId in :QuoteIds
//                                   Order By ProductName__c NULLS LAST]) {
//                                   Order By Item_Numbering__c NULLS LAST]) {
                                   Order By SortOrder  ASC NULLS LAST]) {

                // These are coming in already grouped by the same quote
                // and are sorted by the line number within that group
                
                if (prevQuoteId == null || prevQuoteId != ql.QuoteId) {

                    // start fresh because this is the first iteration OR we made it to 
                    // another group of line items
                    prevQuoteId = ql.QuoteId;
                    lastLineNumber = 0.0; //back to default                   
                }

                // Set the new line numbers as needed
//                if(ql.Item_Numbering__c == null || ql.Item_Numbering__c <= lastLineNumber ) {
//               if(ql.Item_Numbering__c == null || ql.Item_Numbering__c == 0) {

                    ql.Item_Numbering__c = lastLineNumber + 1;
                    
                    // Need to create a "new" in memory line item to break reference to the 
                    // trigger reference, otherwise you will get an error like "cannot update in an After trigger"
 //                   lineItemsForUpdate.add(new QuoteLineItem(id = ql.id, Item_Numbering__c = ql.SortOrder));
                    lineItemsForUpdate.add(new QuoteLineItem(id = ql.id, Item_Numbering__c = ql.Item_Numbering__c));
 //               }
                
                lastLineNumber = ql.Item_Numbering__c;

            } // end for

        }

        if (!lineItemsForUpdate.isEmpty())
            update lineItemsForUpdate; // DML only the changed line items

        QuoteLineItemUtility.TriggerIsRunning = false;
    }
}
 
This is the error:
Apex trigger QuoteLineItemTrigger caused an unexpected exception, contact your administrator: QuoteLineItemTrigger: execution of AfterUpdate caused by: System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: QuoteLineItem.QuoteId: Trigger.QuoteLineItemTrigger: line 34, column 1

Here is my code:
trigger QuoteLineItemTrigger on QuoteLineItem (after insert, after update){  
    
    // prevent recursion
    if (!QuoteLineItemUtility.TriggerIsRunning){
        QuoteLineItemUtility.TriggerIsRunning = true;

        Set<Id> QuoteIds = new Set<Id>();
 
        List<QuoteLineItem> lineItemsForUpdate = new List<QuoteLineItem>();

        // gather IDs first of quotes
        for (QuoteLineItem ql : trigger.new) {
            
                 QuoteIds.add(ql.QuoteId);
        }

        if (!QuoteIds.isEmpty()) {
            // get all line items for all of the above quotes in bulk so that we don't hit governor limits
            Id prevQuoteId;
            Double lastLineNumber;
            // we can query all and these triggered records in an after trigger, nothing missing
            for (QuoteLineItem ql : [Select Id, Item_Numbering__c
                                       From QuoteLineItem 
                                      Where QuoteId in :QuoteIds
                                   Order By QuoteId, Item_Numbering__c NULLS LAST]) {

                // These are coming in already grouped by the same quote
                // and are sorted by the line number within that group
                
                if (prevQuoteId == null || prevQuoteId != ql.QuoteId) {

                    // start fresh because this is the first iteration OR we made it to 
                    // another group of line items
                    prevQuoteId = ql.QuoteId;
                    lastLineNumber = 0.0; //back to default                   
                }

                // Set the new line numbers as needed
                if(ql.Item_Numbering__c == null || ql.Item_Numbering__c == 0) {

                    ql.Item_Numbering__c = lastLineNumber + 1;
                    
                    // Need to create a "new" in memory line item to break reference to the 
                    // trigger reference, otherwise you will get an error like "cannot update in an After trigger"
                    lineItemsForUpdate.add(new QuoteLineItem(id = ql.id, Item_Numbering__c = ql.Item_Numbering__c));
                }
                
                lastLineNumber = ql.Item_Numbering__c;

            } // end for

        }

        if (!lineItemsForUpdate.isEmpty())
            update lineItemsForUpdate; // DML only the changed line items

        QuoteLineItemUtility.TriggerIsRunning = false;
    }
}
Here is the code but I am getting this error:

Error: Compile Error: unexpected syntax: 'missing EOF at '}'' at line 61 column 1
Of course line 61 is the closing curly brace before the Plublic Class declaration
    
trigger QuoteLineItemTrigger on QuoteLineItem (after insert, after update){
    
    // prevent recursion
    if (!QuoteLineItemUtility.TriggerIsRunning){
        QuoteLineItemUtility.TriggerIsRunning = true;

        Set<Id> QuoteIds = new Set<Id>();

        List<QuoteLineItem> lineItemsForUpdate = new List<QuoteLineItem>();

        // gather IDs first of quotes
        for (QuoteLineItem ql : trigger.new) {
            
                 QuoteIds.add(ql.QuoteId);
            }
        }

        if (!QuoteIds.isEmpty()) {
            // get all line items for all of the above quotes in bulk so that we don't hit governor limits
            Id prevQuoteId;
            Integer lastLineNumber;
            // we can query all and these triggered records in an after trigger, nothing missing
            for (QuoteLineItem ql : [Select Id, Item_Numbering__c
                                       From QuoteLineItem 
                                      Where QuoteId in :QuoteIds
                                   Order By QuoteId, Item_Numbering__c NULLS LAST]) {

                // These are coming in already grouped by the same quote
                // and are sorted by the line number within that group
                
                if (prevQuoteId == null || prevQuoteId != ql.QuoteId) {

                    // start fresh because this is the first iteration OR we made it to 
                    // another group of line items
                    prevQuoteId = ql.QuoteId;
                    lastLineNumber = 0; //back to default                   
                }

                // Set the new line numbers as needed
                if(ql.Item_Numbering__c == null || ql.Item_Numbering__c == 0) {

                    ql.Item_Numbering__c = lastLineNumber + 1;
                    
                    // Need to create a "new" in memory line item to break reference to the 
                    // trigger reference, otherwise you will get an error like "cannot update in an After trigger"
                    lineItemsForUpdate.add(new QuoteLineItem(id = ql.id, Item_Numbering__c = ql.Item_Numbering__c));
                }
                
                lastLineNumber = ql.Item_Numbering__c;

            } // end for

        }

        if (!lineItemsForUpdate.isEmpty())
            update lineItemsForUpdate; // DML only the changed line items

        QuoteLineItemUtility.TriggerIsRunning = false;
    }
}

public class QuoteLineItemUtility(){
    public static TriggerIsRunning = false;
}
I would assume the code below should work but I seem to have my syntax wrong. I guess I need to ask is this legal.  Trying to implement an If/else if logic.


  <apex:image width="180" height="40" id="theImage3" value="{!IF(LEFT(relatedTo.rstk__Buyer_Contact__c,3)='Lee',  
"https://geometricsinc123456--rspilot--c.cs97.content.force.com/servlet/servlet.FileDownload?file=0150U00000052qp","{!IF(LEFT(relatedTo.rstk__Buyer_Contact__c,3)='barb',"https://geometricsinc123456--rspilot--c.cs97.content.force.com/servlet/servlet.FileDownload?file=0150U00000050cW",""))}}"></apex:image>
 
I have setup an email template to handle headers and footers. The problem I have is the content inbetween will not align properly.  I get an error when I try to use a div around the middle content and this appears to be due to the use of the apex:repeat code. I think it has to do with the css settings but have not been able to resolve.
Here is the code and I have attached the PDF rendered.  I have a few extra lines in there as I have been testing.
<messaging:emailTemplate subject="Sales Order Invoice Geo" recipientType="User" relatedToType="rstk__FSOINVH__c">
<messaging:htmlEmailBody >
<html>
<head>
<style>
    @page {
     size:a4;
     margin-left: 1.3cm;
     margin-right: 0.4cm;
     margin-top: 8.0cm;
     margin-bottom: 4.5cm;

     @top-left {
           content: element(header);
       }
     @bottom-left {
           content: element(footer);
       }
}
     div.header {
                display: block;
                padding: 1px;
                position: running(header);
                padding-top: 1.0cm;
      }
     div.footer {
                display: block;
                padding: 1px;
                position: running(footer);
      }
    body, table, th, td, div { 
        font:normal normal 95%/1.0 arial, times new roman, verdana; 
    }
    body {
        counter-reset: pg -1;
    }
    table {
        cell-padding: 0;
        cell-spacing: 0;
    }
    #main {

        width:690px;
        background:#ffffff;
    }
    #cont {
        display:block;
        }
    .headerSect {
        width:700px;
    }
    .logoDiv {
        height:56px;
        width:220px;
    }
    .logoDiv img {
        display: block;
        height: 100%;
    }
    .cmpLogo {
        max-height:66px;
        max-width:250px;
    }
    .header2 {
        width:400px;
        border: 1px solid;
        padding: 1px;
    }
    .formTitle {
        float:left;
        font-weight: bold;
        font-size: 140%;
        padding-left:4px;
    }
    .pageNumSect {
        float:right;
        counter-increment: pg;
    }
    div.pageNumSect:before {
        content: "Page " counter(pg) " of " ;
    
    }
    .headerInfo {
        margin-top:24px;
        padding: 2px;
    }
    .hdrInfoLbl {
        font-weight: bold;
    }
    .hdrInfoData {
        font-weight: normal;
    }
    td {
        padding: 2px;
    }
    .addressSect {
        background-color: #000000;
        width:700px;
        margin-top:6px;
        margin-right:2px;
    }
    .addressSect th {
        text-align:center;
        font-weight: bold;
        background-color:#000000;
        color:#ffffff;
        padding: 2px;
    } 
    .addressSect td {
        background-color:#ffffff;
    } 
    .termsSect {
        width:700px;
        margin-top:6px;
        border: 1px solid;
    }
    .termsSect td {
        vertical-align:top;
    }
    .termsSect td:nth-child(1) {
        width: 17%;
        font-weight: bold;
    }
    .termsSect td:nth-child(2) {
        width: 33%;
    }
    .termsSect td:nth-child(3) {
        width: 15%;
        font-weight: bold;
    }
    .termsSect td:nth-child(4) {
        width: 35%;
    }
    table.lines {
        width:700px;
        table-layout:fixed;
        background-color: #ffffff;
        margin-top:6px;
        border-top: 1px solid;
        border-bottom: 1px solid;
        border-right: 1px solid;
        margin-left: auto;
        margin-right:auto;

    }
    table.lines td {
        background-color:#ffffff;
        vertical-align:top;
        padding: 1px;
        border-left: 1px solid black;
    }
    table.lines th {
        background-color:#000000;
        color:#ffffff;
        padding: 0px 0px 0px 0px;
        text-align:center;
        font-weight:bold;
    }
    table.footerSect {
        width:700px;
        margin-top:6px;
        margin-right:2px;
        border-top: 1px solid;
        border-bottom: 1px solid;
        border-right: 1px solid;
    }
    table.footerSect td {
        margin-top: 6px;
        border-left: 1px solid black;
    }
    table.footerSect td td {
        border: none;
    }
    //230
    .totalLabel {
        font-weight: bold;
        width: 90px;
    }
    .totalAmt {
        text-align:right;
        width: 140px;
    }
    .totalSect td {
        border: 0;
    }
    .shippingComments {
        font-weight:bold;
    }
    table.lines tr.lines_content_row td.col_description {
        text-align:left;
        font-weight:bold;
        text-overflow:ellipsis;
        padding-left: 1em;
        white-space: wrap;
        font-size:8pt;
        color:blue;
    }
    table.lines tr.lines_content_row td.col_comment {
        text-align:left;
        font-style:italic;
        padding-left: 1em;
        text-overflow:ellipsis;
    }
    table.lines tr.lines_content_row td.col_empty {
        text-align:left;
        color: #ffffff;
    }
    table.lines tr.lines_content_row td.col_serial {
        text-align:left;
        padding-left: 1em;
        text-overflow:ellipsis;
    }
    table.lines tr.lines_content_row td.col_component {
        text-align:left;
        padding-left:1em;
        text-overflow:ellipsis;
    }
    table.lines tr.lines_content_row td.col_product{
        text-align:left;
        text-overflow:ellipsis;
    }
    table.lines tr.lines_content_row td.col_uom {
        text-align:center;
        font-size:8pt;
    }
    table.lines tr.lines_content_row td.col_shipper {
        text-align:center;
    }
    table.lines tr.lines_content_row td.col_tax {
        text-align:center;
    }
    table.lines tr.lines_content_row td {
        text-align:right; 
        overflow:hidden;
        text-overflow:clip;
        white-space:nowrap;
    }
    table.lines {
        padding-bottom: {!38 - relatedTo.rstk__numLines__c}em;
    }
    .wrapper{position:relative;}
    .right,.left{width:50%; position:absolute;}
    .right{right:0;}
    .left{left:0;}

</style>
</head>
<body>
<div id="main">
<!--apex:repeat value="{pages}" var="page"-->
  <div class="header">
    <div class="headerSect">
      <table cellspacing="0" cellpadding="0" border="1">
      <tr><td valign="middle" width="300px">
        <div class="logoDiv">
<!--             <apex:image height="48px"  width="204px" value="{!relatedTo.rstk__companylogo__c}" rendered="{!!ISBLANK(relatedTo.rstk__companylogo__c)}"/>-->
           <apex:image styleClass=".cmpLogo" value="{!relatedTo.rstk__companylogo__c}" rendered="{!!ISBLANK(relatedTo.rstk__companylogo__c)}"/> 
       </div>
      </td><td  width="400px">
 <!--       <div class="header2">-->
            <div class="formTitle">Sales Invoice</div>
           <div class="pageNumSect">{!relatedTo.rstk__pages__c}</div>

             <apex:panelGrid styleClass="headerInfo" columnClasses="hdrInfoLbl,hdrInfoData" columns="2" width="100%">
                <apex:outputText value="Invoice Number"/>
                <apex:outputText value="{!relatedTo.rstk__invoiceno__c}"/>
                <apex:outputText value="Invoice Date"/>
                <apex:outputText value="{0,date,short}">
                  <apex:param value="{!relatedTo.rstk__invdate__c}"/>
                </apex:outputText>
                <apex:outputText value="Sales Order Number"/>
                <apex:outputText value="{!relatedTo.rstk__order__c}"/>
                <apex:outputText value="Customer PO Number"/>
                <apex:outputText value="{!relatedTo.rstk__custpo__c}"/>
            </apex:panelGrid>
   <!--     </div> -->
      </td></tr></table>
    </div>
        <table  border="0" cellspacing="0" cellpadding="0" class="lines" style="float:left">
        <tr class="lines_header_row">
          <th width="4%" >Line</th>
          <th width="44%">Product</th>
          <th width="4%" >UOM</th>
          <th width="12%">Shipper</th>
          <th width="7%" >Quantity</th>
          <th width="9%" >Unit Price</th>
          <th width="7%" >Discount</th>
          <th width="10%">Extension</th>
          <th width="3%" >Tax</th>
        </tr></table>

  </div>
  <div class="footer">
    <table class="footerSect" cellpadding="5" cellspacing="0" border="1">
     <tr><td>
      <apex:outputText value="These items are controlled by the U.S. Government and authorized for export only to the country of ultimate destination for use by the ultimate consignee or end-user(s) herein identified. They may not be resold, transferred, or otherwise disposed of, to any other country or to any person other than the authorized ultimate consignee or end-user(s), either in their original form or after being incorporated into other items, without first obtaining approval from the U. S. government or as otherwise authorized by the U. S. law and regulations."/>
     </td></tr>
    </table>
 
  </div>
   <table  border="0" cellspacing="0" cellpadding="0" class="lines"  style="float:left">
      <tr>
          <th width="4%" >Line</th>
          <th width="44%">Product</th>
          <th width="4%" >UOM</th>
          <th width="12%">Shipper</th>
          <th width="7%" >Quantity</th>
          <th width="9%" >Unit Price</th>
          <th width="7%" >Discount</th>
          <th width="10%">Extension</th>
          <th width="3%" >Tax</th>
        </tr>
        <apex:repeat var="l" value="{!relatedTo.rstk__lines__r}">
        <tr class="lines_content_row">
            <apex:variable var="isSpanRow" value="{!l.rstk__linetype__c='Description'}" />
            <!-- Description Panel - Spans Across Table -->
            <apex:outputPanel layout="none" rendered="{! isSpanRow }">
                <!-- Blank Line Number Column -->
                <td></td> 
                <!-- Description Column -->
                <td class="col_description" colspan="8" >{!l.rstk__comment__c}</td> 
            </apex:outputPanel>
            <!-- Standard Panel - No Spans -->
            <apex:outputPanel layout="none" rendered="{! !isSpanRow }">
                <!-- Line Number Column -->
                <td class="col_lineno">{!l.rstk__invline__c}</td>
                <!-- Product Column -->
                <apex:variable var="productClass" value="{! 'col_product' + IF(l.rstk__linetype__c='Empty',' col_empty','') + IF(l.rstk__linetype__c='Detail', '', '') + IF(l.rstk__linetype__c='Prepayment','','') + IF(l.rstk__linetype__c='PrepaymentApplied','','') + IF(l.rstk__linetype__c='Comment',' col_comment', '') + IF(l.rstk__linetype__c='Serial', ' col_serial', '') + IF(l.rstk__linetype__c='Component', ' col_component', '') }"/>
                <apex:variable var="productDisplayVal" value="{! '' + IF(l.rstk__linetype__c='Empty', 'X', '') + IF(l.rstk__linetype__c='Detail', l.rstk__prod__c, '') + IF(OR(l.rstk__linetype__c='Prepayment', l.rstk__linetype__c='PrepaymentApplied', l.rstk__linetype__c='Comment', l.rstk__linetype__c='Serial'), l.rstk__comment__c, '') + IF(l.rstk__linetype__c='Component', l.rstk__component__c , '') }"/>
                <td class="{!productClass}">
                    {!productDisplayVal}
                </td>
                <!-- Unit Of Measure Column -->
                <td class="col_uom">{!l.rstk__uom__c}</td>
                <!-- Shipper Column -->
                <td class="col_shipper">{!l.rstk__shipper__c}</td>
                <!-- Quantity Column -->
                <td class="col_qty">
                    <apex:outputText value="{0,Number,###,###,###,##0.00}" rendered="{!OR(l.rstk__linetype__c='Detail',l.rstk__linetype__c='Prepayment')}">
                        <apex:param value="{!l.rstk__qty__c}"/>
                    </apex:outputText>
                </td>
                <!-- Unit Price Column -->
                <td class="col_unitprice">
                    <apex:outputText value="{0,Number,###,###,###,##0.00}" rendered="{!l.rstk__linetype__c='Detail'}">
                        <apex:param value="{!l.rstk__price__c}"/>
                    </apex:outputText>
                    <apex:outputText value="{0,Number,###,###,###,##0.00}" rendered="{!l.rstk__linetype__c='Component'}">
                        <apex:param value="{!l.rstk__unitprice__c}"/>
                    </apex:outputText>
                </td>
                <!-- Discount Column -->
                <td class="col_discount">
                    <apex:outputText value="{0,Number,###,###,###,##0.00}%" rendered="{!!ISBLANK(l.rstk__discpct__c)}">
                        <apex:param value="{!l.rstk__discpct__c}"/>
                    </apex:outputText>
                </td>
                <!-- Extension Column -->
                <td class="col_extension">
                    <apex:variable var="isPrepaymentApplied" value="{! l.rstk__linetype__c='PrepaymentApplied' }"/>
                    <apex:variable var="extensionAmount" value="{! IF(isPrepaymentApplied, (l.rstk__price__c - l.rstk__discamt__c) * l.rstk__qty__c , (l.rstk__price__c - l.rstk__discamt__c) * l.rstk__qty__c )}"/>
                    <apex:outputText value="{0,Number,###,###,###,##0.00}">
                        <apex:param value="{!extensionAmount}"/>
                    </apex:outputText>
                </td>
                <!-- Tax Column -->
                 <td class="col_tax">
                     <apex:outputText value="{!IF(OR(relatedTo.rstk__taxexempt__c, l.rstk__taxexempt__c),'','Y')}" rendered="{!!ISBLANK(l.rstk__invline__c)}"/>
                 </td>
            </apex:outputPanel>
        </tr>
        </apex:repeat>
    </table>

<!--/apex:repeat-->
  <table  cellpadding="0" cellspacing="0" border="1" width="100%" style="float:left">
    <tr><td width="460px" valign="top">
      <div style="overflow:hidden;max-height:85px;"><apex:outputText escape="false"  value="{!relatedTo.rstk__extcomment__c}"/></div>
      </td>
      <td width="240px">
      <apex:panelGrid styleClass="totalSect" columnClasses="totalLabel,totalAmt" columns="2" width="240px" >
        <apex:outputText value="SubTotal"/>
        <apex:outputText value="{0,Number,###,###,###,###,##0.00}">
            <apex:param value="{!relatedTo.rstk__total__c}"/>
        </apex:outputText>
        <apex:outputText value="Discount" rendered="{!AND(!ISNULL(relatedTo.rstk__discamt__c), relatedTo.rstk__discamt__c>0)}"/>
        <apex:outputText value="({0,Number,###,###,###,###,##0.00})" rendered="{!AND(!ISNULL(relatedTo.rstk__discamt__c), relatedTo.rstk__discamt__c>0)}">
            <apex:param value="{!relatedTo.rstk__discamt__c}"/>
        </apex:outputText>
        <apex:outputText value="Shipping"/>
        <apex:outputText value="{0,Number,###,###,###,###,##0.00}">
            <apex:param value="{!relatedTo.rstk__freightamt__c+relatedTo.rstk__handlingamt__c+relatedTo.rstk__packageamt__c}"/>
        </apex:outputText>
        <apex:outputText value="Tax"/>
        <apex:outputText value="{0,Number,###,###,###,###,##0.00}">
            <apex:param value="{!relatedTo.rstk__taxamt__c}"/>
        </apex:outputText>
        <apex:outputText value="Prepayment"/>
        <apex:outputText value="({0,Number,###,###,###,###,##0.00})">
            <apex:param value="{!relatedTo.rstk__totalppya__c}"/>
        </apex:outputText>
        <apex:outputText value="Invoice Total"/>
        <apex:outputText value="{0,Number,###,###,###,###,##0.00}">
            <apex:param value="{!relatedTo.rstk__grandtotal__c - relatedTo.rstk__totalppya__c}"/>
        </apex:outputText>
      </apex:panelGrid>
    </td></tr>
  </table>
</div>
</body>
</html>
</messaging:htmlEmailBody>
</messaging:emailTemplate>

 
I created a simple Apex Class and VFC to display my query results in an email template.
The only thing it displays is the correct size of the list and a blank POId . No List results.
*********************Apex Code
global class POComponent
{
global string POId
    {
    get;
    set;
    }
global integer leng
    {
    get;
    set;
    }
global List<rstk__poline__c> RSNPOLine2
    {
    get;
    set;
    }
public POComponent()
    {
    POComponentCore();
    }
public List<rstk__poline__c> POComponentCore()
    {
    POId = ApexPages.currentPage().getParameters().get('id');
    List<rstk__poline__c> RSNPOLine2  = new List<rstk__poline__c>();
    RSNPOLine2 = [SELECT rstk__poline_lne__c,rstk__poline_item__c, rstk__poline_descr__c FROM rstk__poline__c where rstk__poline_ordno__c = :POId];
     leng = RSNPOLine2.size();
    return RSNPOLine2;
    }
}
*************************VFC code:
<apex:component controller="POComponent" access="global">
<apex:attribute name="configproducts" description="DCPId" type="String" assignTo="{!POId}"/>
            <table>
            <apex:repeat var="arr" value="{!RSNPOLine2}">
                <tr>
                    <td style="width: 010mm;   height: 004mm;">Just a test inside VFC</td>
                    <td style="width: 025mm;   height: 004mm;">
                        <div style="width: 100%; max-width:100%; white-space: nowrap; overflow: hidden;">{!arr.rstk__poline_descr__c}</div>
                    </td>
                    <td style="width: 067mm; height: 004mm; ">
                        <div style="width: 100%; max-width:100%; white-space: nowrap; overflow: hidden;">{!arr.rstk__poline_item__c}</div>
                    </td>
                    <td style="width: 010mm;   height: 004mm;">
                        <div style="width: 100%; max-width:100%; white-space: nowrap; overflow: hidden; text-align: right;">{!arr.rstk__poline_lne__c}</div>
                    </td>
                    <td style="width: 010mm;   height: 004mm; ">
                        <div style="width: 100%; max-width:100%; white-space: nowrap; overflow: hidden; text-align: left; margin-left: 1mm;">CCCCC</div>
                    </td>
                    <td style="width: 025mm;   height: 004mm;">
                        <div style="width: 100%; max-width:100%; white-space: nowrap; overflow: hidden; text-align: right;">1111.99</div>
                    </td>
                </tr>
             </apex:repeat>
            </table>
                <table>
                <tr><td>This is outside the repeat loop, list size = {!leng} and POId is {!POId}</td></tr></table>
</apex:component>
******************Email Template code:
<messaging:emailTemplate subject="Purchase Order" recipientType="User" relatedToType="rstk__PO_Print_Header__c">
<messaging:htmlEmailBody >
<html>
<head>
<style type="text/css" media="print">
 @page {
     size:A4;
     margin-left: 0.8cm;
     margin-right: 0.8cm;
     margin-top: 12.0cm;
     margin-bottom: 4.5cm;
     @top-center {
           content: element(header);
       }
     @bottom-left {
           content: element(footer);
       }
}
 </style>
 </head>
 <body>
        <c:POComponent configproducts="{!relatedTo.Id}"/>
</body>
</html>
</messaging:htmlEmailBody>
</messaging:emailTemplate>
I am trying to concatenate two fields and insert into a Note.
It works fine when I use text but fails when I try to use a textarea
InstrumentName__c is a text(255) field and IntrumentProblem_c is textarea(255)
The following works fine:

var repnew3 = new sforce.SObject('Note');
repnew3.ParentId = qr.records.Id;
repnew3.Title = '{!Case.Subject}';
// combine 
repnew3.Body = '{!Case.InstrumentName__c}';
result3 = sforce.connection.create([repnew3]);

 This will not work:

var repnew3 = new sforce.SObject('Note');
repnew3.ParentId = qr.records.Id;
repnew3.Title = '{!Case.Subject}';
// combine 
repnew3.Body = '{!Case.InstrumentProblem__c}';
result3 = sforce.connection.create([repnew3]);

Is there a conversion process require or does the Note.Body field not accept textarea?

Ultimately I want to concatenate the two as follows:
var repnew3 = new sforce.SObject('Note');
repnew3.ParentId = qr.records.Id;
repnew3.Title = '{!Case.Subject}';
// combine 
repnew3.Body = 'Problem: ' + '{!Case.InstrumentProblem__c}' + '  Name: ' + '{!Case.InstrumentName__c}';
result3 = sforce.connection.create([repnew3]);

This is being used as a button action on the Case layout.
The error returned upon a delete of a Quote Line Item is:

There were custom validation error(s) encountered while saving the affected record(s). The first validation error encountered was "Apex trigger QuoteLineItemTrigger caused an unexpected exception, contact your administrator: QuoteLineItemTrigger: execution of AfterDelete caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.QuoteLineItemTrigger: line 12, column 1". 

This is the code, I tried after delete and before delete. It works fine for after insert and after update.

trigger QuoteLineItemTrigger on QuoteLineItem (after insert, after update, after delete){  
    
    // prevent recursion
    if (!QuoteLineItemUtility.TriggerIsRunning){
        QuoteLineItemUtility.TriggerIsRunning = true;

        Set<Id> QuoteIds = new Set<Id>();
 
        List<QuoteLineItem> lineItemsForUpdate = new List<QuoteLineItem>();

        // gather IDs first of quotes
       for (QuoteLineItem ql : trigger.new) {   // line 12
            
                 QuoteIds.add(ql.QuoteId);
        }

        if (!QuoteIds.isEmpty()) {
            // get all line items for all of the above quotes in bulk so that we don't hit governor limits
            Id prevQuoteId;
            Double lastLineNumber;
            // we can query all and these triggered records in an after trigger, nothing missing
            for (QuoteLineItem ql : [Select Id, Item_Numbering__c,QuoteId,SortOrder
                                       From QuoteLineItem 
                                      Where QuoteId in :QuoteIds
//                                   Order By ProductName__c NULLS LAST]) {
//                                   Order By Item_Numbering__c NULLS LAST]) {
                                   Order By SortOrder  ASC NULLS LAST]) {

                // These are coming in already grouped by the same quote
                // and are sorted by the line number within that group
                
                if (prevQuoteId == null || prevQuoteId != ql.QuoteId) {

                    // start fresh because this is the first iteration OR we made it to 
                    // another group of line items
                    prevQuoteId = ql.QuoteId;
                    lastLineNumber = 0.0; //back to default                   
                }

                // Set the new line numbers as needed
//                if(ql.Item_Numbering__c == null || ql.Item_Numbering__c <= lastLineNumber ) {
//               if(ql.Item_Numbering__c == null || ql.Item_Numbering__c == 0) {

                    ql.Item_Numbering__c = lastLineNumber + 1;
                    
                    // Need to create a "new" in memory line item to break reference to the 
                    // trigger reference, otherwise you will get an error like "cannot update in an After trigger"
 //                   lineItemsForUpdate.add(new QuoteLineItem(id = ql.id, Item_Numbering__c = ql.SortOrder));
                    lineItemsForUpdate.add(new QuoteLineItem(id = ql.id, Item_Numbering__c = ql.Item_Numbering__c));
 //               }
                
                lastLineNumber = ql.Item_Numbering__c;

            } // end for

        }

        if (!lineItemsForUpdate.isEmpty())
            update lineItemsForUpdate; // DML only the changed line items

        QuoteLineItemUtility.TriggerIsRunning = false;
    }
}
 
This is the error:
Apex trigger QuoteLineItemTrigger caused an unexpected exception, contact your administrator: QuoteLineItemTrigger: execution of AfterUpdate caused by: System.SObjectException: SObject row was retrieved via SOQL without querying the requested field: QuoteLineItem.QuoteId: Trigger.QuoteLineItemTrigger: line 34, column 1

Here is my code:
trigger QuoteLineItemTrigger on QuoteLineItem (after insert, after update){  
    
    // prevent recursion
    if (!QuoteLineItemUtility.TriggerIsRunning){
        QuoteLineItemUtility.TriggerIsRunning = true;

        Set<Id> QuoteIds = new Set<Id>();
 
        List<QuoteLineItem> lineItemsForUpdate = new List<QuoteLineItem>();

        // gather IDs first of quotes
        for (QuoteLineItem ql : trigger.new) {
            
                 QuoteIds.add(ql.QuoteId);
        }

        if (!QuoteIds.isEmpty()) {
            // get all line items for all of the above quotes in bulk so that we don't hit governor limits
            Id prevQuoteId;
            Double lastLineNumber;
            // we can query all and these triggered records in an after trigger, nothing missing
            for (QuoteLineItem ql : [Select Id, Item_Numbering__c
                                       From QuoteLineItem 
                                      Where QuoteId in :QuoteIds
                                   Order By QuoteId, Item_Numbering__c NULLS LAST]) {

                // These are coming in already grouped by the same quote
                // and are sorted by the line number within that group
                
                if (prevQuoteId == null || prevQuoteId != ql.QuoteId) {

                    // start fresh because this is the first iteration OR we made it to 
                    // another group of line items
                    prevQuoteId = ql.QuoteId;
                    lastLineNumber = 0.0; //back to default                   
                }

                // Set the new line numbers as needed
                if(ql.Item_Numbering__c == null || ql.Item_Numbering__c == 0) {

                    ql.Item_Numbering__c = lastLineNumber + 1;
                    
                    // Need to create a "new" in memory line item to break reference to the 
                    // trigger reference, otherwise you will get an error like "cannot update in an After trigger"
                    lineItemsForUpdate.add(new QuoteLineItem(id = ql.id, Item_Numbering__c = ql.Item_Numbering__c));
                }
                
                lastLineNumber = ql.Item_Numbering__c;

            } // end for

        }

        if (!lineItemsForUpdate.isEmpty())
            update lineItemsForUpdate; // DML only the changed line items

        QuoteLineItemUtility.TriggerIsRunning = false;
    }
}
Here is the code but I am getting this error:

Error: Compile Error: unexpected syntax: 'missing EOF at '}'' at line 61 column 1
Of course line 61 is the closing curly brace before the Plublic Class declaration
    
trigger QuoteLineItemTrigger on QuoteLineItem (after insert, after update){
    
    // prevent recursion
    if (!QuoteLineItemUtility.TriggerIsRunning){
        QuoteLineItemUtility.TriggerIsRunning = true;

        Set<Id> QuoteIds = new Set<Id>();

        List<QuoteLineItem> lineItemsForUpdate = new List<QuoteLineItem>();

        // gather IDs first of quotes
        for (QuoteLineItem ql : trigger.new) {
            
                 QuoteIds.add(ql.QuoteId);
            }
        }

        if (!QuoteIds.isEmpty()) {
            // get all line items for all of the above quotes in bulk so that we don't hit governor limits
            Id prevQuoteId;
            Integer lastLineNumber;
            // we can query all and these triggered records in an after trigger, nothing missing
            for (QuoteLineItem ql : [Select Id, Item_Numbering__c
                                       From QuoteLineItem 
                                      Where QuoteId in :QuoteIds
                                   Order By QuoteId, Item_Numbering__c NULLS LAST]) {

                // These are coming in already grouped by the same quote
                // and are sorted by the line number within that group
                
                if (prevQuoteId == null || prevQuoteId != ql.QuoteId) {

                    // start fresh because this is the first iteration OR we made it to 
                    // another group of line items
                    prevQuoteId = ql.QuoteId;
                    lastLineNumber = 0; //back to default                   
                }

                // Set the new line numbers as needed
                if(ql.Item_Numbering__c == null || ql.Item_Numbering__c == 0) {

                    ql.Item_Numbering__c = lastLineNumber + 1;
                    
                    // Need to create a "new" in memory line item to break reference to the 
                    // trigger reference, otherwise you will get an error like "cannot update in an After trigger"
                    lineItemsForUpdate.add(new QuoteLineItem(id = ql.id, Item_Numbering__c = ql.Item_Numbering__c));
                }
                
                lastLineNumber = ql.Item_Numbering__c;

            } // end for

        }

        if (!lineItemsForUpdate.isEmpty())
            update lineItemsForUpdate; // DML only the changed line items

        QuoteLineItemUtility.TriggerIsRunning = false;
    }
}

public class QuoteLineItemUtility(){
    public static TriggerIsRunning = false;
}