Exercise 18

Sales Vouchers With Default Ledgers

Published


This exercise imports Sales Vouchers with GST and stock items from Excel into Tally Prime, like the Sales Vouchers With GST With Inventory exercise. The difference is that the sheet has no ledger-name columns. The Sales, IGST, CGST and SGST ledger names are built with FORMULA from the tax percentages, for example SALES 18% and CGST 9%, and the same formulas are used to create those default ledgers and to post the voucher entries.

The Excel sheet

Each row is one item of an invoice: Item (column G), Qty (H), Rate (I) and the taxable Amount (J), followed by the tax percentages (K to M) and tax amounts (N to P), and the HSN code and description (Q, R). Invoice SV-TEST-001 is inter-state (IGST), invoice SV-TEST-002 is intra-state (CGST and SGST). The tax amounts are already calculated in the sheet.

ABCDEFGHIJKLMNOPQR
1inv-noinv-datepartygstinstatecountryitemqtyrateamountigst-ratecgst-ratesgst-rateigst-amtcgst-amtsgst-amthsnhsn-description
2SV-TEST-00101-04-2026Test Customer Karnataka Pvt Ltd29ABCDE1234F1Z5KarnatakaIndiaTest Widget A101500.0015000.0018002700.000.000.0084798999Machinery parts
3SV-TEST-00202-04-2026Test Customer Maharashtra Pvt Ltd27PQRSX5678L1Z2MaharashtraIndiaTest Widget B52000.0010000.000990.00900.00900.0084879000Machinery parts

Step 1 — Create the Unit and Stock Item masters

A single unit NOS is created, and the Stock Item is created from column G with that unit, the HSN code and description (columns Q, R) and the GST rates. The Central Tax and State Tax rates come from columns L and M, or half of the IGST percentage (K) when those are empty; the Integrated Tax rate comes from column K, or the sum of L and M.

  <!-- Unit Master: single unit "NOS" (numbers) used by every stock item and the NOS suffix on qty/rate -->
  <MASTER TYPE="UNIT">
    <NAME>NOS</NAME>
    <ISSIMPLEUNIT>Yes</ISSIMPLEUNIT>
  </MASTER>

  <!-- Stock Item Master: one item per distinct value in column G, with GST and HSN details from the CSV -->
  <MASTER TYPE="STOCKITEM">
    <NAME.LIST>
      <NAME COLUMNREFERENCE="G"/>
    </NAME.LIST>
    <BASEUNITS>NOS</BASEUNITS>
    <!-- GST applicability set to "Applicable" (Tally predefined value, hence the ~[~ marker) -->
    <GSTAPPLICABLE FORMULA="=&quot;~[~ Applicable&quot;"/>
    <GSTTYPEOFSUPPLY>Goods</GSTTYPEOFSUPPLY>

    <!-- GST details are defined at item level ("Specify Details Here"), effective from 01-Apr-2026 (FY start) -->
    <GSTDETAILS.LIST>
      <APPLICABLEFROM>20260401</APPLICABLEFROM>
      <CALCULATIONTYPE>On Value</CALCULATIONTYPE>
      <!-- Q = HSN/SAC code, R = HSN description -->
      <HSNCODE COLUMNREFERENCE="Q"/>
      <HSN COLUMNREFERENCE="R"/>
      <TAXABILITY>Taxable</TAXABILITY>
      <SRCOFGSTDETAILS>Specify Details Here</SRCOFGSTDETAILS>

      <!-- Applies to every state ("Any"); the rate heads below are mutually exclusive in practice -->
      <STATEWISEDETAILS.LIST>
        <STATENAME>~[~ Any</STATENAME>

        <!-- CGST rate: use column L if given, else half of IGST rate (K/2) when only IGST rate is supplied, else 0 -->
        <RATEDETAILS.LIST>
          <GSTRATEDUTYHEAD>Central Tax</GSTRATEDUTYHEAD>
          <GSTRATEVALUATIONTYPE>Based on Value</GSTRATEVALUATIONTYPE>
          <GSTRATE FORMULA="=If(Round(L#,2)&gt;0,Round(L#,2),If(K#&gt;0,Round(K#/2,2),0))"/>
        </RATEDETAILS.LIST>

        <!-- SGST rate: same logic as CGST, driven by column M -->
        <RATEDETAILS.LIST>
          <GSTRATEDUTYHEAD>State Tax</GSTRATEDUTYHEAD>
          <GSTRATEVALUATIONTYPE>Based on Value</GSTRATEVALUATIONTYPE>
          <GSTRATE FORMULA="=If(Round(M#,2)&gt;0,Round(M#,2),If(K#&gt;0,Round(K#/2,2),0))"/>
        </RATEDETAILS.LIST>

        <!-- IGST rate: use column K if given, else CGST+SGST (L+M) so the item always carries the full GST rate -->
        <RATEDETAILS.LIST>
          <GSTRATEDUTYHEAD>Integrated Tax</GSTRATEDUTYHEAD>
          <GSTRATEVALUATIONTYPE>Based on Value</GSTRATEVALUATIONTYPE>
          <GSTRATE FORMULA="=If(Round(K#,2)&gt;0,Round(K#,2),Round(L#+M#,2))"/>
        </RATEDETAILS.LIST>

        <!-- Cess and State Cess are not used in this template -->
        <RATEDETAILS.LIST>
          <GSTRATEDUTYHEAD>Cess</GSTRATEDUTYHEAD>
          <GSTRATEVALUATIONTYPE>~[~ Not Applicable</GSTRATEVALUATIONTYPE>
        </RATEDETAILS.LIST>

        <RATEDETAILS.LIST>
          <GSTRATEDUTYHEAD>State Cess</GSTRATEDUTYHEAD>
          <GSTRATEVALUATIONTYPE>~[~ Not Applicable</GSTRATEVALUATIONTYPE>
        </RATEDETAILS.LIST>
      </STATEWISEDETAILS.LIST>
    </GSTDETAILS.LIST>

    <!-- HSN details block (separate from GST details): keeps the HSN code/description on the item master -->
    <HSNDETAILS.LIST>
      <APPLICABLEFROM>20260401</APPLICABLEFROM>
      <HSNCODE COLUMNREFERENCE="Q"/>
      <HSN COLUMNREFERENCE="R"/>
      <SRCOFHSNDETAILS>Specify Details Here</SRCOFHSNDETAILS>
    </HSNDETAILS.LIST>
  </MASTER>

Step 2 — Create the Party Ledger master

The party (column C) is created under Sundry Debtors with bill-wise tracking on. The GST registration type depends on the GSTIN in column D (Regular when given, otherwise Unregistered), the country defaults to India, and the state and place of supply come from column E.

  <!-- Party Ledger Master: customer ledger (column C) created under Sundry Debtors with bill-wise tracking -->
  <MASTER TYPE="LEDGER">
    <NAME.LIST>
      <NAME COLUMNREFERENCE="C"/>
    </NAME.LIST>
    <PARENT>Sundry Debtors</PARENT>
    <!-- Bill-wise on so the invoice number (column A) can be tracked as a "New Ref" for outstanding/receipts -->
    <ISBILLWISEON>Yes</ISBILLWISEON>
    <ISCOSTCENTRESON>No</ISCOSTCENTRESON>
    <!-- Blank GSTIN (D) => Unregistered, otherwise Regular. Country defaults to India when F is blank. State is proper-cased (E) -->
    <GSTREGISTRATIONTYPE FORMULA="=if(len(trim(D#))=0,&quot;Unregistered&quot;,&quot;Regular&quot;)"/>
    <PARTYGSTIN FORMULA="=trim(D#)"/>
    <COUNTRYNAME FORMULA="=if(len(trim(F#))=0,&quot;India&quot;,F#)"/>
    <STATENAME FORMULA="=proper(trim(E#))"/>
    <LEDSTATENAME FORMULA="=proper(trim(E#))"/>

    <!-- GST registration details of the party (type, state, place of supply, GSTIN), effective from 01-Apr-2026 -->
    <LEDGSTREGDETAILS.LIST>
      <APPLICABLEFROM>20260401</APPLICABLEFROM>
      <GSTREGISTRATIONTYPE FORMULA="=if(len(trim(D#))=0,&quot;Unregistered/Consumer&quot;,&quot;Regular&quot;)"/>
      <STATE FORMULA="=proper(trim(E#))"/>
      <PLACEOFSUPPLY FORMULA="=proper(trim(E#))"/>
      <GSTIN FORMULA="=trim(D#)"/>
    </LEDGSTREGDETAILS.LIST>

    <!-- Mailing details: mailing name same as ledger name, plus state and country -->
    <LEDMAILINGDETAILS.LIST>
      <APPLICABLEFROM>20260401</APPLICABLEFROM>
      <MAILINGNAME COLUMNREFERENCE="C"/>
      <STATE FORMULA="=proper(trim(E#))"/>
      <COUNTRY FORMULA="=if(len(trim(F#))=0,&quot;India&quot;,F#)"/>
    </LEDMAILINGDETAILS.LIST>
  </MASTER>

Step 3 — Create the default Sales and Tax Ledgers

This is the key idea of the exercise. There are no ledger-name columns, so each ledger NAME is a FORMULA. The Sales ledger is named SALES [rate]%, where K#+L#+M# gives the total GST rate whichever tax type applies. The tax ledgers are named IGST [rate]%, CGST [rate]% and SGST [rate]% and are created under Duties & Taxes. When the tax amount is 0 the formula returns an empty name, so that ledger is not created. The same formulas are used in the voucher, so the names always match.

  <!-- Default Sales Ledger: named "SALES [rate]%" (e.g. SALES 18%), one ledger per GST slab; K+L+M gives the total rate whichever tax type applies -->
  <MASTER TYPE="LEDGER">
    <NAME.LIST>
      <NAME FORMULA="=&quot;SALES &quot; &amp; (K#+L#+M#) &amp; &quot;%&quot;"/>
    </NAME.LIST>
    <PARENT>Sales Accounts</PARENT>
    <ISCOSTCENTRESON>No</ISCOSTCENTRESON>
    <ISBILLWISEON>No</ISBILLWISEON>
    <AFFECTSSTOCK>Yes</AFFECTSSTOCK>
    <USEFORVAT>No</USEFORVAT>
    <GSTTYPEOFSUPPLY>Goods</GSTTYPEOFSUPPLY>
  </MASTER>

  <!-- Default IGST Ledger: "IGST [rate]%" under Duties and Taxes; name is blank (ledger skipped) when IGST amount (N) is 0 -->
  <MASTER TYPE="LEDGER">
    <NAME.LIST>
      <NAME FORMULA="=if(Round(N#,2)=0,&quot;&quot;,&quot;IGST &quot; &amp; K# &amp; &quot;%&quot;)"/>
    </NAME.LIST>
    <PARENT>Duties &amp; Taxes</PARENT>
    <ISCOSTCENTRESON>No</ISCOSTCENTRESON>
    <AFFECTSSTOCK>No</AFFECTSSTOCK>
    <GSTDUTYHEAD>Integrated Tax</GSTDUTYHEAD>
    <TAXTYPE>GST</TAXTYPE>
  </MASTER>
  <!-- Default CGST Ledger: "CGST [rate]%" under Duties and Taxes; name is blank (ledger skipped) when CGST amount (O) is 0 -->
  <MASTER TYPE="LEDGER">
    <NAME.LIST>
      <NAME FORMULA="=if(Round(O#,2)=0,&quot;&quot;,&quot;CGST &quot; &amp; L# &amp; &quot;%&quot;)"/>
    </NAME.LIST>
    <PARENT>Duties &amp; Taxes</PARENT>
    <ISCOSTCENTRESON>No</ISCOSTCENTRESON>
    <AFFECTSSTOCK>No</AFFECTSSTOCK>
    <GSTDUTYHEAD>Central Tax</GSTDUTYHEAD>
    <TAXTYPE>GST</TAXTYPE>
  </MASTER>

  <!-- Default SGST Ledger: "SGST [rate]%" under Duties and Taxes; name is blank (ledger skipped) when SGST amount (P) is 0 -->
  <MASTER TYPE="LEDGER">
    <NAME.LIST>
      <NAME FORMULA="=if(Round(P#,2)=0,&quot;&quot;,&quot;SGST &quot; &amp; M# &amp; &quot;%&quot;)"/>
    </NAME.LIST>
    <PARENT>Duties &amp; Taxes</PARENT>
    <ISCOSTCENTRESON>No</ISCOSTCENTRESON>
    <AFFECTSSTOCK>No</AFFECTSSTOCK>
    <GSTDUTYHEAD>State Tax</GSTDUTYHEAD>
    <TAXTYPE>GST</TAXTYPE>
  </MASTER>

Step 4 — Write the Voucher tags

One Sales voucher is created for each invoice number, in Item Invoice mode.

  <!-- Sales Voucher: one voucher per invoice number (rows sharing column A are grouped into one voucher) -->
  <VOUCHER>
    <!-- Fixed prefix + invoice number gives a stable GUID, so re-importing the same file updates instead of duplicating -->
    <GUID FORMULA="=&quot;udi-SDL1-&quot; &amp; A#"/>
    <DATE COLUMNREFERENCE="B"/>
    <EFFECTIVEDATE COLUMNREFERENCE="B"/>
    <VOUCHERTYPENAME>Sales</VOUCHERTYPENAME>
    <VOUCHERNUMBER COLUMNREFERENCE="A"/>
    <REFERENCE COLUMNREFERENCE="A"/>
    <ISINVOICE>Yes</ISINVOICE>
    <PERSISTEDVIEW>Invoice Voucher View</PERSISTEDVIEW>
    <VCHENTRYMODE>Item Invoice</VCHENTRYMODE>
    <ISGSTOVERRIDDEN>No</ISGSTOVERRIDDEN>

    <!-- Party GST and place-of-supply details; place of supply (state, column E) drives IGST vs CGST/SGST in Tally -->
    <PARTYGSTIN FORMULA="=trim(D#)"/>
    <GSTREGISTRATIONTYPE FORMULA="=if(len(trim(D#))=0,&quot;Unregistered&quot;,&quot;Regular&quot;)"/>
    <STATENAME FORMULA="=proper(trim(E#))"/>
    <COUNTRYOFRESIDENCE FORMULA="=if(len(trim(F#))=0,&quot;India&quot;,F#)"/>
    <PLACEOFSUPPLY FORMULA="=proper(trim(E#))"/>
    <PARTYNAME COLUMNREFERENCE="C"/>
    <PARTYLEDGERNAME COLUMNREFERENCE="C"/>
    <BASICBASEPARTYNAME COLUMNREFERENCE="C"/>
    <BASICBUYERNAME COLUMNREFERENCE="C"/>

    <!-- Party Ledger Entry (debit): grouped by invoice number; amount = taxable value + IGST + CGST + SGST,
         negative because the party is debited (ISDEEMEDPOSITIVE = Yes) -->
    <LEDGERENTRIES.LIST GROUPBY="=A#">
      <LEDGERNAME COLUMNREFERENCE="C"/>
      <ISDEEMEDPOSITIVE>Yes</ISDEEMEDPOSITIVE>
      <AMOUNT FORMULA="={Round(J#,2)+Round(N#,2)+Round(O#,2)+Round(P#,2)}*-1"/>

      <!-- Bill allocation: creates the invoice number as a "New Ref" bill for outstanding tracking; skipped if invoice no. is blank -->
      <BILLALLOCATIONS.LIST SKIP="=Len(trim(A#))=0">
        <NAME COLUMNREFERENCE="A"/>
        <BILLTYPE>New Ref</BILLTYPE>
        <AMOUNT FORMULA="={Round(J#,2)+Round(N#,2)+Round(O#,2)+Round(P#,2)}*-1"/>
      </BILLALLOCATIONS.LIST>
    </LEDGERENTRIES.LIST>

    <!-- Inventory Entry: one line per CSV row (SCROLL="YES" repeats it for each item row of the same invoice);
         qty (H), rate (I) and amount (J) are taken as-is, with the NOS unit appended -->
    <ALLINVENTORYENTRIES.LIST SCROLL="YES">
      <STOCKITEMNAME COLUMNREFERENCE="G"/>
      <GSTOVRDNISREVCHARGEAPPL>No</GSTOVRDNISREVCHARGEAPPL>
      <GSTOVRDNTAXABILITY>Taxable</GSTOVRDNTAXABILITY>
      <GSTOVRDNTYPEOFSUPPLY>Goods</GSTOVRDNTYPEOFSUPPLY>
      <GSTSOURCETYPE>Stock Item</GSTSOURCETYPE>
      <HSNSOURCETYPE>Stock Item</HSNSOURCETYPE>

      <!-- HSN code and description from CSV -->
      <GSTHSNNAME COLUMNREFERENCE="Q"/>
      <GSTHSNDESCRIPTION COLUMNREFERENCE="R"/>

      <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
      <RATE FORMULA="=I# &amp; &quot;/NOS&quot;"/>
      <AMOUNT FORMULA="=Round(J#,2)"/>
      <ACTUALQTY FORMULA="=H# &amp; &quot; NOS&quot;"/>
      <BILLEDQTY FORMULA="=H# &amp; &quot; NOS&quot;"/>

      <RATEDETAILS.LIST>
        <GSTRATEDUTYHEAD>Central Tax</GSTRATEDUTYHEAD>
        <GSTRATEVALUATIONTYPE>Based on Value</GSTRATEVALUATIONTYPE>
        <GSTRATE FORMULA="=If(Round(L#,2)&gt;0,Round(L#,2),If(K#&gt;0,Round(K#/2,2),0))"/>
      </RATEDETAILS.LIST>

      <RATEDETAILS.LIST>
        <GSTRATEDUTYHEAD>State Tax</GSTRATEDUTYHEAD>
        <GSTRATEVALUATIONTYPE>Based on Value</GSTRATEVALUATIONTYPE>
        <GSTRATE FORMULA="=If(Round(M#,2)&gt;0,Round(M#,2),If(K#&gt;0,Round(K#/2,2),0))"/>
      </RATEDETAILS.LIST>

      <RATEDETAILS.LIST>
        <GSTRATEDUTYHEAD>Integrated Tax</GSTRATEDUTYHEAD>
        <GSTRATEVALUATIONTYPE>Based on Value</GSTRATEVALUATIONTYPE>
        <GSTRATE FORMULA="=If(Round(K#,2)&gt;0,Round(K#,2),Round(L#+M#,2))"/>
      </RATEDETAILS.LIST>

      <RATEDETAILS.LIST>
        <GSTRATEDUTYHEAD>State Cess</GSTRATEDUTYHEAD>
        <GSTRATEVALUATIONTYPE>~[~ Not Applicable</GSTRATEVALUATIONTYPE>
      </RATEDETAILS.LIST>

      <!-- Sales ledger posting (credit) for this item line, using the auto-created "SALES [rate]%" ledger -->
      <ACCOUNTINGALLOCATIONS.LIST>
        <LEDGERNAME FORMULA="=&quot;SALES &quot; &amp; (K#+L#+M#) &amp; &quot;%&quot;"/>
        <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
        <AMOUNT FORMULA="=Round(J#,2)"/>
      </ACCOUNTINGALLOCATIONS.LIST>

      <!-- Stock movement out of the default godown and batch (change names if your company uses others) -->
      <BATCHALLOCATIONS.LIST>
        <GODOWNNAME>Main Location</GODOWNNAME>
        <BATCHNAME>Primary Batch</BATCHNAME>
        <DESTINATIONGODOWNNAME>Main Location</DESTINATIONGODOWNNAME>
        <AMOUNT FORMULA="=Round(J#,2)"/>
        <ACTUALQTY FORMULA="=H# &amp; &quot; NOS&quot;"/>
        <BILLEDQTY FORMULA="=H# &amp; &quot; NOS&quot;"/>
      </BATCHALLOCATIONS.LIST>
    </ALLINVENTORYENTRIES.LIST>

    <!-- Tax ledger entries (credit): grouped by tax ledger name so same-rate lines in one invoice merge into one entry;
         SKIP drops the entry when that tax amount is 0 (e.g. no IGST on an intra-state sale) -->
    <!-- IGST Ledger Entry: amount from column N -->
    <LEDGERENTRIES.LIST
      GROUPBY="=if(Round(N#,2)=0,&quot;&quot;,&quot;IGST &quot; &amp; K# &amp; &quot;%&quot;)"
      SKIP="={Round(N#,2)}=0">
      <LEDGERNAME FORMULA="=if(Round(N#,2)=0,&quot;&quot;,&quot;IGST &quot; &amp; K# &amp; &quot;%&quot;)"/>
      <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
      <AMOUNT FORMULA="={Round(N#,2)}"/>
    </LEDGERENTRIES.LIST>

    <!-- CGST Ledger Entry: amount from column O -->
    <LEDGERENTRIES.LIST
      GROUPBY="=if(Round(O#,2)=0,&quot;&quot;,&quot;CGST &quot; &amp; L# &amp; &quot;%&quot;)"
      SKIP="={Round(O#,2)}=0">
      <LEDGERNAME FORMULA="=if(Round(O#,2)=0,&quot;&quot;,&quot;CGST &quot; &amp; L# &amp; &quot;%&quot;)"/>
      <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
      <AMOUNT FORMULA="={Round(O#,2)}"/>
    </LEDGERENTRIES.LIST>

    <!-- SGST Ledger Entry: amount from column P -->
    <LEDGERENTRIES.LIST
      GROUPBY="=if(Round(P#,2)=0,&quot;&quot;,&quot;SGST &quot; &amp; M# &amp; &quot;%&quot;)"
      SKIP="={Round(P#,2)}=0">
      <LEDGERNAME FORMULA="=if(Round(P#,2)=0,&quot;&quot;,&quot;SGST &quot; &amp; M# &amp; &quot;%&quot;)"/>
      <ISDEEMEDPOSITIVE>No</ISDEEMEDPOSITIVE>
      <AMOUNT FORMULA="={Round(P#,2)}"/>
    </LEDGERENTRIES.LIST>

  </VOUCHER>
Remarks:
  1. The default ledger names are built from the tax percentages. Fill either IGST (K), or CGST and SGST (L, M) for a row, never both.
  2. The sales amount is not posted as a separate ledger entry: it is allocated inside each inventory line through ACCOUNTINGALLOCATIONS.LIST.
  3. The tax amounts are not calculated by the XML tags. Calculate them in the sheet, for example =J2*K2/100.
  4. The GUID uses a fixed prefix plus the invoice number, so importing the same file again updates the vouchers instead of duplicating them.
  5. The godown Main Location and batch Primary Batch are Tally defaults; change them if your company uses other names.
  6. Leave the GSTIN blank for an unregistered party.
Sample files: Download the sample Excel sheet and matching XML tags file for this exercise. Download sales-vouchers-with-default-ledgers.zip

Ready to import your Excel data into Tally?

Download udiMagic and start a 14-day free trial — no credit card required.

Download udiMagic View Pricing