CSharp Code For Making a Double Entry General Ledger Posting (Method 1)

INTRODUCTION

Here I will discuss a programming technique I use in the C# platform to perform a double entry posting to a general ledger in a Chart Of Accounts application I made for a long time customer. This is actually the first of two methods used in this program. I will discuss the second method in a later article.

THE FIRST STEP

Initially, we need to key in the total amount to process for the double entry posting operation. You enter this amount in either the “Total Debit Amount” or “Total Credit Amount” textbox in the screen below (Figures 1 & 2). The transaction type and transaction description also need to be entered. Next, click the corresponding button for either the “Total Debit Amount For Double Entry Posting” or “Total Credit Amount For Double Entry Posting”. One thing to note – this step is not yet performing the double entry posting - we are merely setting up for doing that next.



Figure 1: Entry



Figure 2: Entry Posting

Next, I present the underlying C# code that facilitates this preliminary step. For the button, “Total Debit Amount For Double Entry Posting”:

  1. long  autonum_var;  
  2. long[] convert_to_number = new long[GLAMOUNTS];  
  3. string transaction_str, debit_str, stringAutoNumber;  
  4. char[] totalamount = new char[GLAMOUNTS];  
  5.   
  6.   
  7.     if (textBox_transactiondescription.Text.Length > 0 && textBox_totaldebitamount.Text.Length > 0 && comboBox_transactiontype.Text.Length > 0)  
  8.     {  
  9.   
  10.   
  11.     result = MessageBox.Show("Do you want to proceed with this double entry posting transaction?""Verification Mode", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);  
  12.   
  13.     if (result == DialogResult.Yes)  
  14.     {  
  15.   
  16.         Cursor.Current = new Cursor(currdir + "Busy_l.cur");  
  17.   
  18.   
  19.         // get current date.  
  20.         DateTime saveNow = DateTime.Now;  
  21.         dateString = saveNow.ToString(datePatt);  
  22.   
  23.         // grab data from Winform controls.  
  24.         transaction_str = textBox_transactiondescription.Text;  
  25.         debit_str = textBox_totaldebitamount.Text;  
  26.         remaining_offsetting_balance_str = textBox_totaldebitamount.Text;  
  27.         textBox_remainingbalanceoftotal.Text = textBox_totaldebitamount.Text;  
  28.   
  29.         // set the chart of accounts list box to purple to signal to the  
  30.         // user that it is engaged to perform the debit side of the 2 postings  
  31.         // to the gl account to be clicked on in the next step.   
  32.         listBox_chartofaccountslisting.BackColor = Color.MediumPurple;  
  33.         // disable buttons used to denote the first posting as a debit or a credit.  
  34.         button_totaldebitamountfordoubleentryposting.Enabled = false;  
  35.         button_totalcreditamountfordoubleentryposting.Enabled = false;  
  36.   
  37.         // set internal flags.  
  38.         MakeListBoxSandyBrown = 0;  
  39.         MakeListBoxMediumPurple = 1;  
  40.         MakeListBoxTomato = 0;  
  41.   
  42.         ApplyOffSettingDebits = 1;  
  43.         ApplyOffSettingCredits = 0;  
  44.   
  45.   
  46.         // retrieve the last used auto-generated transaction posting  
  47.         // number and increment it to the next one and then save that  
  48.         // to the same data file.  
  49.         StreamReader streamobj3 = new StreamReader(currdir + "autonumber.txt");  
  50.         streamobj3.BaseStream.Seek(0, SeekOrigin.Begin);  
  51.         stringAutoNumber = streamobj3.ReadLine();  
  52.         streamobj3.Close();  
  53.   
  54.         for (a = 0; a < 3; a++)  
  55.         {  
  56.             convert_to_number[a] = 0;  
  57.             if (stringAutoNumber.Substring(a, 1) == "0") convert_to_number[a] = 0;  
  58.             if (stringAutoNumber.Substring(a, 1) == "1") convert_to_number[a] = 1;  
  59.             if (stringAutoNumber.Substring(a, 1) == "2") convert_to_number[a] = 2;  
  60.             if (stringAutoNumber.Substring(a, 1) == "3") convert_to_number[a] = 3;  
  61.             if (stringAutoNumber.Substring(a, 1) == "4") convert_to_number[a] = 4;  
  62.             if (stringAutoNumber.Substring(a, 1) == "5") convert_to_number[a] = 5;  
  63.             if (stringAutoNumber.Substring(a, 1) == "6") convert_to_number[a] = 6;  
  64.             if (stringAutoNumber.Substring(a, 1) == "7") convert_to_number[a] = 7;  
  65.             if (stringAutoNumber.Substring(a, 1) == "8") convert_to_number[a] = 8;  
  66.             if (stringAutoNumber.Substring(a, 1) == "9") convert_to_number[a] = 9;  
  67.         }  
  68.         autonum_var = ((convert_to_number[0] * 100) + (convert_to_number[1] * 10) + (convert_to_number[2] * 1));  
  69.         autonum_var++;  
  70.         if (autonum_var > 999) {  
  71.             autonum_var = 0;  
  72.         }  
  73.   
  74.         for (a = 0; a < 3; a++) charVal_auto_number[a] = (char)48;  
  75.         countervar = 2;  
  76.         do  
  77.         {  
  78.             longresult = Math.DivRem(autonum_var, 10, out long2);  
  79.             autonum_var = longresult;  
  80.             if (long2 == 0) charVal_auto_number[countervar] = (char)48;  
  81.             if (long2 == 1) charVal_auto_number[countervar] = (char)49;  
  82.             if (long2 == 2) charVal_auto_number[countervar] = (char)50;  
  83.             if (long2 == 3) charVal_auto_number[countervar] = (char)51;  
  84.             if (long2 == 4) charVal_auto_number[countervar] = (char)52;  
  85.             if (long2 == 5) charVal_auto_number[countervar] = (char)53;  
  86.             if (long2 == 6) charVal_auto_number[countervar] = (char)54;  
  87.             if (long2 == 7) charVal_auto_number[countervar] = (char)55;  
  88.             if (long2 == 8) charVal_auto_number[countervar] = (char)56;  
  89.             if (long2 == 9) charVal_auto_number[countervar] = (char)57;  
  90.             countervar--;  
  91.         } while (autonum_var > 0);  
  92.   
  93.         if (File.Exists(currdir + "autonumber.txt"))  
  94.         {  
  95.             File.Delete(currdir + "autonumber.txt");  
  96.         }  
  97.   
  98.         FileStream fstreamobj2 = new FileStream(currdir + "autonumber.txt", FileMode.Create);  
  99.         StreamWriter writerobj2 = new StreamWriter(fstreamobj2);  
  100.         writerobj2.WriteLine(charVal_auto_number);  
  101.         writerobj2.Close();  
  102.         fstreamobj2.Close();  
  103.   
  104.   
  105.         // zero out the "total debit amount" textbox.  
  106.         this.textBox_totaldebitamount.Text = "      0.00";  
  107.   
  108.   
  109.         Cursor.Current = Cursors.Default;  
  110.   
  111.   
  112.     }  
  113.   
  114.   
  115. }  
  116. else  
  117. {  
  118.   
  119.     MessageBox.Show("The debit and/or transaction description and/or transaction type field(s) may be empty...please fill them in and retry...""Error Mode");  
  120.   
  121. }
Now for the button, “Total Credit Amount For Double Entry Posting”:
  1. long  autonum_var;  
  2.  long[] convert_to_number = new long[GLAMOUNTS];  
  3.  string transaction_str, credit_str, stringAutoNumber;  
  4.  char[] totalamount = new char[GLAMOUNTS];  
  5.   
  6.   
  7.      if (textBox_transactiondescription.Text.Length > 0 && textBox_totalcreditamount.Text.Length > 0 && comboBox_transactiontype.Text.Length > 0)  
  8.      {  
  9.   
  10.   
  11.      result = MessageBox.Show("Do you want to proceed with this double entry posting transaction?""Verification Mode", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);  
  12.   
  13.      if (result == DialogResult.Yes)  
  14.      {  
  15.   
  16.          Cursor.Current = new Cursor(currdir + "Busy_l.cur");  
  17.   
  18.   
  19.          // get current date.  
  20.          DateTime saveNow = DateTime.Now;  
  21.          dateString = saveNow.ToString(datePatt);  
  22.   
  23.          // grab data from Winform controls.  
  24.          transaction_str = textBox_transactiondescription.Text;  
  25.          credit_str = textBox_totalcreditamount.Text;  
  26.          remaining_offsetting_balance_str = textBox_totalcreditamount.Text;  
  27.          textBox_remainingbalanceoftotal.Text = textBox_totalcreditamount.Text;  
  28.   
  29.          // set the chart of accounts list box to purple to signal to the  
  30.          // user that it is engaged to perform the credit side of the 2 postings  
  31.          // to the gl account to be clicked on in the next step.   
  32.          listBox_chartofaccountslisting.BackColor = Color.MediumPurple;  
  33.          // disable buttons used to denote the first posting as a debit or a credit.  
  34.          button_totaldebitamountfordoubleentryposting.Enabled = false;  
  35.          button_totalcreditamountfordoubleentryposting.Enabled = false;  
  36.   
  37.          // set internal flags.  
  38.          MakeListBoxSandyBrown = 0;  
  39.          MakeListBoxMediumPurple = 1;  
  40.          MakeListBoxTomato = 0;  
  41.   
  42.          ApplyOffSettingDebits = 0;  
  43.          ApplyOffSettingCredits = 1;  
  44.   
  45.   
  46.          // retrieve the last used auto-generated transaction posting  
  47.          // number and increment it to the next one and then save that  
  48.          // to the same data file.  
  49.          StreamReader streamobj3 = new StreamReader(currdir + "autonumber.txt");  
  50.          streamobj3.BaseStream.Seek(0, SeekOrigin.Begin);  
  51.          stringAutoNumber = streamobj3.ReadLine();  
  52.          streamobj3.Close();  
  53.   
  54.          for (a = 0; a < 3; a++)  
  55.          {  
  56.              convert_to_number[a] = 0;  
  57.              if (stringAutoNumber.Substring(a, 1) == "0") convert_to_number[a] = 0;  
  58.              if (stringAutoNumber.Substring(a, 1) == "1") convert_to_number[a] = 1;  
  59.              if (stringAutoNumber.Substring(a, 1) == "2") convert_to_number[a] = 2;  
  60.              if (stringAutoNumber.Substring(a, 1) == "3") convert_to_number[a] = 3;  
  61.              if (stringAutoNumber.Substring(a, 1) == "4") convert_to_number[a] = 4;  
  62.              if (stringAutoNumber.Substring(a, 1) == "5") convert_to_number[a] = 5;  
  63.              if (stringAutoNumber.Substring(a, 1) == "6") convert_to_number[a] = 6;  
  64.              if (stringAutoNumber.Substring(a, 1) == "7") convert_to_number[a] = 7;  
  65.              if (stringAutoNumber.Substring(a, 1) == "8") convert_to_number[a] = 8;  
  66.              if (stringAutoNumber.Substring(a, 1) == "9") convert_to_number[a] = 9;  
  67.          }  
  68.          autonum_var = ((convert_to_number[0] * 100) + (convert_to_number[1] * 10) + (convert_to_number[2] * 1));  
  69.          autonum_var++;  
  70.          if (autonum_var > 999)  
  71.          {  
  72.              autonum_var = 0;  
  73.          }  
  74.   
  75.          for (a = 0; a < 3; a++) charVal_auto_number[a] = (char)48;  
  76.          countervar = 2;  
  77.          do  
  78.          {  
  79.              longresult = Math.DivRem(autonum_var, 10, out long2);  
  80.              autonum_var = longresult;  
  81.              if (long2 == 0) charVal_auto_number[countervar] = (char)48;  
  82.              if (long2 == 1) charVal_auto_number[countervar] = (char)49;  
  83.              if (long2 == 2) charVal_auto_number[countervar] = (char)50;  
  84.              if (long2 == 3) charVal_auto_number[countervar] = (char)51;  
  85.              if (long2 == 4) charVal_auto_number[countervar] = (char)52;  
  86.              if (long2 == 5) charVal_auto_number[countervar] = (char)53;  
  87.              if (long2 == 6) charVal_auto_number[countervar] = (char)54;  
  88.              if (long2 == 7) charVal_auto_number[countervar] = (char)55;  
  89.              if (long2 == 8) charVal_auto_number[countervar] = (char)56;  
  90.              if (long2 == 9) charVal_auto_number[countervar] = (char)57;  
  91.              countervar--;  
  92.          } while (autonum_var > 0);  
  93.   
  94.          if (File.Exists(currdir + "autonumber.txt"))  
  95.          {  
  96.              File.Delete(currdir + "autonumber.txt");  
  97.          }  
  98.   
  99.          FileStream fstreamobj2 = new FileStream(currdir + "autonumber.txt", FileMode.Create);  
  100.          StreamWriter writerobj2 = new StreamWriter(fstreamobj2);  
  101.          writerobj2.WriteLine(charVal_auto_number);  
  102.          writerobj2.Close();  
  103.          fstreamobj2.Close();  
  104.   
  105.   
  106.          // zero out the "total credit amount" textbox.  
  107.          this.textBox_totalcreditamount.Text = "      0.00";  
  108.   
  109.   
  110.          Cursor.Current = Cursors.Default;  
  111.   
  112.   
  113.      }  
  114.   
  115.   
  116.  }  
  117.  else  
  118.  {  
  119.   
  120.      MessageBox.Show("The credit and/or transaction description and/or transaction type field(s) may be empty...please fill them in and retry...""Error Mode");  
  121.   
  122.  }
NOW FOR THE POSTING CODE

After keying in a debit or credit amount for the initial posting operation and clicking the corresponding button beneath its textbox, we are now ready to proceed with the double entry posting operation. Notice that the color for the listing for Chart of Accounts has changed from “sandy brown” to “medium purple” (Figures 3 & 4). This is a sort of heads up I devised to alert the operator to the fact that we are now in the initial posting phase of the double entry posting operation.



Figure 3: Posting



Figure 4: purple

Notice the amount that was originally entered for the total debit or credit amount is now in the textbox for the remaining balance. Just below that is a textbox for the amount to be applied. The operator may enter any number of amounts in this textbox as long as the cumulative total does not exceed the original remaining balance amount. In fact, the operator cannot exit this mode and proceed to the next step until the full amount to be posted has been reduced to zero by successive posting operations. To post an amount after keying in how much of the remaining balance you want to apply, just double click on a selected ledger in the “medium purple” colored Chart of Accounts listing.

After the remaining balance of the initial posting phase has been reduced to zero, we will enter the offsetting posting phase as evidenced by the “medium purple” color of the Chart of Accounts listing turning to “tomato color” (Figures 5 & 6). Mechanically, this functions identically to the initial posting phase.



Figure 5: medium Purple



Figure 6: Tomato

After the offsetting posting phase is complete, the listing color for Chart of Accounts simply reverts back to “sandy brown” color to signal it is ready for another double entry posting operation. Here is the code listing that facilitates the posting operation:
  1. int amount_flag;  
  2.      long runningbalance_to_chararray, debit_var, credit_var, runningbalance;  
  3.      long remaining_balance, post_amount, new_remaining_balance,choose_record_datafile_offset;  
  4.      long[] convert_to_number = new long[GLAMOUNTS];  
  5.      string transaction_str, debit_str, credit_str, remaining_balance_str, post_amount_str;  
  6.      string listBox1_String, stringBalance;  
  7.      char[] totalamount = new char[GLAMOUNTS];  
  8.      char[] charVal_date, charVal_tranaction, charVal_debit, charVal_credit;  
  9.    
  10.      if (listBox_chartofaccountslisting.SelectedIndex != -1)  
  11.      {  
  12.   
  13.          // retrieve the selected ledger info from the Chart of Accounts listing.  
  14.          listBox1_String = listBox_chartofaccountslisting.Text;  
  15.   
  16.          // calculate the data file stream offset for the selected general ledger.  
  17.          for (a = 0; a < 5; a++)  
  18.          {  
  19.              convert_to_number[a] = 0;  
  20.              if (listBox1_String.Substring((listBox1_String.Length - 5) + a, 1) == "0") convert_to_number[a] = 0;  
  21.              if (listBox1_String.Substring((listBox1_String.Length - 5) + a, 1) == "1") convert_to_number[a] = 1;  
  22.              if (listBox1_String.Substring((listBox1_String.Length - 5) + a, 1) == "2") convert_to_number[a] = 2;  
  23.              if (listBox1_String.Substring((listBox1_String.Length - 5) + a, 1) == "3") convert_to_number[a] = 3;  
  24.              if (listBox1_String.Substring((listBox1_String.Length - 5) + a, 1) == "4") convert_to_number[a] = 4;  
  25.              if (listBox1_String.Substring((listBox1_String.Length - 5) + a, 1) == "5") convert_to_number[a] = 5;  
  26.              if (listBox1_String.Substring((listBox1_String.Length - 5) + a, 1) == "6") convert_to_number[a] = 6;  
  27.              if (listBox1_String.Substring((listBox1_String.Length - 5) + a, 1) == "7") convert_to_number[a] = 7;  
  28.              if (listBox1_String.Substring((listBox1_String.Length - 5) + a, 1) == "8") convert_to_number[a] = 8;  
  29.              if (listBox1_String.Substring((listBox1_String.Length - 5) + a, 1) == "9") convert_to_number[a] = 9;  
  30.          }  
  31.          choose_record_datafile_offset = ((convert_to_number[0] * 10000) + (convert_to_number[1] * 1000) + (convert_to_number[2] * 100) + (convert_to_number[3] * 10) + (convert_to_number[4] * 1)) * GLMASTERLEN;  
  32.   
  33.          if (listBox1_String.Substring(0, 4) == "GL A") MessageBox.Show("Invalid selection...""Error Mode");  
  34.          if (listBox1_String.Substring(0, 4) != "GL A")  
  35.          {  
  36.      
  37.              // open a file stream to the master Chart of Accounts data file and  
  38.              // go to the record for the selected ledger. then read it and  
  39.              // parse out the general ledger file name.  
  40.              StreamReader streamobj2 = new StreamReader(currdir + "mastcoa.txt");  
  41.              streamobj2.BaseStream.Seek(choose_record_datafile_offset, SeekOrigin.Begin);  
  42.              stringVal = streamobj2.ReadLine();  
  43.              streamobj2.Close();  
  44.   
  45.              strfile = stringVal.Substring(45, 8);  
  46.              strfile = strfile + ".txt";  
  47.     
  48.              // if the color of the Chart of Accounts listing is sandy brown, then  
  49.              // display the contents of the selected general ledger in the transactions  
  50.              // listing at the top of the screen.  
  51.              if (MakeListBoxSandyBrown == 1)  
  52.              {  
  53.     
  54.                  this.textBox2.Text = stringVal.Substring(0, 41);  
  55.                  this.textBox3.Text = stringVal.Substring(41, 4);  
  56.     
  57.                  listBox2.Items.Clear();  
  58.                  listBox2.Items.Add("Date    " + "\t" + "Txn" + "\t" + "TYPE" + "\t" + "Transaction Description     " + "\t" + "Debit     " + "\t" + "Credit   " + "\t" + "BALANCE  ");  
  59.   
  60.                  FileInfo datafileinfo = new FileInfo(currdir + strfile);  
  61.                  sizeofdatafile = datafileinfo.Length;  
  62.                  StreamReader streamobj = new StreamReader(currdir + strfile);  
  63.                  streamobj.BaseStream.Seek(0, SeekOrigin.Begin);  
  64.   
  65.                  runningbalance = 0;  
  66.                  datafileoffset = 0;  
  67.                  do  
  68.                  {  
  69.   
  70.                      stringVal = streamobj.ReadLine();  
  71.   
  72.                      for (a = 0; a < GLAMOUNTS; a++)  
  73.                      {  
  74.                          convert_to_number[a] = 0;  
  75.                          if (stringVal.Substring(50 + a, 1) == "0") convert_to_number[a] = 0;  
  76.                          if (stringVal.Substring(50 + a, 1) == "1") convert_to_number[a] = 1;  
  77.                          if (stringVal.Substring(50 + a, 1) == "2") convert_to_number[a] = 2;  
  78.                          if (stringVal.Substring(50 + a, 1) == "3") convert_to_number[a] = 3;  
  79.                          if (stringVal.Substring(50 + a, 1) == "4") convert_to_number[a] = 4;  
  80.                          if (stringVal.Substring(50 + a, 1) == "5") convert_to_number[a] = 5;  
  81.                          if (stringVal.Substring(50 + a, 1) == "6") convert_to_number[a] = 6;  
  82.                          if (stringVal.Substring(50 + a, 1) == "7") convert_to_number[a] = 7;  
  83.                          if (stringVal.Substring(50 + a, 1) == "8") convert_to_number[a] = 8;  
  84.                          if (stringVal.Substring(50 + a, 1) == "9") convert_to_number[a] = 9;  
  85.                      }  
  86.                      debit_var = ((convert_to_number[0] * 100000000) + (convert_to_number[1] * 10000000) + (convert_to_number[2] * 1000000) + (convert_to_number[3] * 100000) + (convert_to_number[4] * 10000) + (convert_to_number[5] * 1000) + (convert_to_number[6] * 100) + (convert_to_number[8] * 10) + (convert_to_number[9] * 1));  
  87.   
  88.                      for (a = 0; a < GLAMOUNTS; a++)  
  89.                      {  
  90.                          convert_to_number[a] = 0;  
  91.                          if (stringVal.Substring(60 + a, 1) == "0") convert_to_number[a] = 0;  
  92.                          if (stringVal.Substring(60 + a, 1) == "1") convert_to_number[a] = 1;  
  93.                          if (stringVal.Substring(60 + a, 1) == "2") convert_to_number[a] = 2;  
  94.                          if (stringVal.Substring(60 + a, 1) == "3") convert_to_number[a] = 3;  
  95.                          if (stringVal.Substring(60 + a, 1) == "4") convert_to_number[a] = 4;  
  96.                          if (stringVal.Substring(60 + a, 1) == "5") convert_to_number[a] = 5;  
  97.                          if (stringVal.Substring(60 + a, 1) == "6") convert_to_number[a] = 6;  
  98.                          if (stringVal.Substring(60 + a, 1) == "7") convert_to_number[a] = 7;  
  99.                          if (stringVal.Substring(60 + a, 1) == "8") convert_to_number[a] = 8;  
  100.                          if (stringVal.Substring(60 + a, 1) == "9") convert_to_number[a] = 9;  
  101.                      }  
  102.                      credit_var = ((convert_to_number[0] * 100000000) + (convert_to_number[1] * 10000000) + (convert_to_number[2] * 1000000) + (convert_to_number[3] * 100000) + (convert_to_number[4] * 10000) + (convert_to_number[5] * 1000) + (convert_to_number[6] * 100) + (convert_to_number[8] * 10) + (convert_to_number[9] * 1));  
  103.   
  104.                      runningbalance = runningbalance - debit_var + credit_var;  
  105.   
  106.                      for (a = 0; a < 10; a++) totalamount[a] = (char)32;  
  107.                      totalamount[6] = (char)48;  
  108.                      totalamount[7] = (char)46;  
  109.                      totalamount[8] = (char)48;  
  110.                      totalamount[9] = (char)48;  
  111.                      runningbalance_to_chararray = runningbalance;  
  112.                      if (runningbalance < 0)  
  113.                      {  
  114.                          runningbalance_to_chararray = 0 - runningbalance;  
  115.                      }  
  116.                      countervar = 9;  
  117.                      do  
  118.                      {  
  119.                          longresult = Math.DivRem(runningbalance_to_chararray, 10, out long2);  
  120.                          runningbalance_to_chararray = longresult;  
  121.                          if (long2 == 0) totalamount[countervar] = (char)48;  
  122.                          if (long2 == 1) totalamount[countervar] = (char)49;  
  123.                          if (long2 == 2) totalamount[countervar] = (char)50;  
  124.                          if (long2 == 3) totalamount[countervar] = (char)51;  
  125.                          if (long2 == 4) totalamount[countervar] = (char)52;  
  126.                          if (long2 == 5) totalamount[countervar] = (char)53;  
  127.                          if (long2 == 6) totalamount[countervar] = (char)54;  
  128.                          if (long2 == 7) totalamount[countervar] = (char)55;  
  129.                          if (long2 == 8) totalamount[countervar] = (char)56;  
  130.                          if (long2 == 9) totalamount[countervar] = (char)57;  
  131.                          countervar--;  
  132.                          if (countervar == 7)  
  133.                          {  
  134.                              totalamount[countervar] = (char)46;  
  135.                              countervar--;  
  136.                          }  
  137.                      } while (runningbalance_to_chararray > 0);  
  138.   
  139.                      stringBalance = new string(totalamount);  
  140.                      if (runningbalance < 0)  
  141.                      {  
  142.                          stringBalance = "- " + stringBalance;  
  143.                      }  
  144.                      else  
  145.                      {  
  146.                          stringBalance = "+ " + stringBalance;  
  147.                      }  
  148.   
  149.                      listBox2.Items.Add(stringVal.Substring(0, 8) + "\t " + stringVal.Substring(70, 3) + "\t " + stringVal.Substring(8, 2) + "\t" + stringVal.Substring(10, 28) + "\t" + stringVal.Substring(50, 10) + "\t" + stringVal.Substring(60, 10) + "\t" + stringBalance);  
  150.   
  151.                      datafileoffset = datafileoffset + GLDETAILEN;  
  152.   
  153.                  } while (datafileoffset < sizeofdatafile);  
  154.                  streamobj.Close();  
  155.     
  156.                  this.textBox_totaldebitamount.Text = "      0.00";  
  157.                  this.textBox_totalcreditamount.Text = "      0.00";  
  158.                  this.textBox_transactiondescription.Text = "";  
  159.     
  160.                  Cursor.Current = Cursors.Default;  
  161.   
  162.                  }  
  163.   
  164.                
  165.              // process the selected general ledger when the Chart of Accounts  
  166.              // listing color is medium purple (initial posting) or tomato color  
  167.              // (offsetting posting).  
  168.              if (MakeListBoxMediumPurple == 1 || MakeListBoxTomato == 1)  
  169.              {  
  170.   
  171.   
  172.                  // grab today's date as well as the remaining balance and the   
  173.                  // amount to be applied to this posting operation.  
  174.                  DateTime saveNow = DateTime.Now;  
  175.                  dateString = saveNow.ToString(datePatt);  
  176.   
  177.                  remaining_balance_str = textBox_remainingbalanceoftotal.Text;  
  178.                  post_amount_str = textBox_enteramounttobeapplied.Text;  
  179.   
  180.   
  181.                  for (a = 0; a < GLAMOUNTS; a++)  
  182.                  {  
  183.                      convert_to_number[a] = 0;  
  184.                      if (remaining_balance_str.Substring(a, 1) == "0") convert_to_number[a] = 0;  
  185.                      if (remaining_balance_str.Substring(a, 1) == "1") convert_to_number[a] = 1;  
  186.                      if (remaining_balance_str.Substring(a, 1) == "2") convert_to_number[a] = 2;  
  187.                      if (remaining_balance_str.Substring(a, 1) == "3") convert_to_number[a] = 3;  
  188.                      if (remaining_balance_str.Substring(a, 1) == "4") convert_to_number[a] = 4;  
  189.                      if (remaining_balance_str.Substring(a, 1) == "5") convert_to_number[a] = 5;  
  190.                      if (remaining_balance_str.Substring(a, 1) == "6") convert_to_number[a] = 6;  
  191.                      if (remaining_balance_str.Substring(a, 1) == "7") convert_to_number[a] = 7;  
  192.                      if (remaining_balance_str.Substring(a, 1) == "8") convert_to_number[a] = 8;  
  193.                      if (remaining_balance_str.Substring(a, 1) == "9") convert_to_number[a] = 9;  
  194.                  }  
  195.                  remaining_balance = ((convert_to_number[0] * 100000000) + (convert_to_number[1] * 10000000) + (convert_to_number[2] * 1000000) + (convert_to_number[3] * 100000) + (convert_to_number[4] * 10000) + (convert_to_number[5] * 1000) + (convert_to_number[6] * 100) + (convert_to_number[8] * 10) + (convert_to_number[9] * 1));  
  196.   
  197.                  for (a = 0; a < GLAMOUNTS; a++)  
  198.                  {  
  199.                      convert_to_number[a] = 0;  
  200.                      if (post_amount_str.Substring(a, 1) == "0") convert_to_number[a] = 0;  
  201.                      if (post_amount_str.Substring(a, 1) == "1") convert_to_number[a] = 1;  
  202.                      if (post_amount_str.Substring(a, 1) == "2") convert_to_number[a] = 2;  
  203.                      if (post_amount_str.Substring(a, 1) == "3") convert_to_number[a] = 3;  
  204.                      if (post_amount_str.Substring(a, 1) == "4") convert_to_number[a] = 4;  
  205.                      if (post_amount_str.Substring(a, 1) == "5") convert_to_number[a] = 5;  
  206.                      if (post_amount_str.Substring(a, 1) == "6") convert_to_number[a] = 6;  
  207.                      if (post_amount_str.Substring(a, 1) == "7") convert_to_number[a] = 7;  
  208.                      if (post_amount_str.Substring(a, 1) == "8") convert_to_number[a] = 8;  
  209.                      if (post_amount_str.Substring(a, 1) == "9") convert_to_number[a] = 9;  
  210.                  }  
  211.                  post_amount = ((convert_to_number[0] * 100000000) + (convert_to_number[1] * 10000000) + (convert_to_number[2] * 1000000) + (convert_to_number[3] * 100000) + (convert_to_number[4] * 10000) + (convert_to_number[5] * 1000) + (convert_to_number[6] * 100) + (convert_to_number[8] * 10) + (convert_to_number[9] * 1));  
  212.   
  213.   
  214.                  // make sure the amount to be posted is always less than or equal to  
  215.                  // the remaining balance before proceeding.  
  216.                  if (post_amount <= remaining_balance)  
  217.                  {  
  218.   
  219.   
  220.                      // if we are in offsetting posting mode, then show this message...  
  221.                      if (MakeListBoxTomato == 1)  
  222.                      {  
  223.                          result = MessageBox.Show("Do you want to process this offsetting general ledger transaction?""Verification Mode", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);  
  224.                      }  
  225.                      else   // show this message for initial posting mode...  
  226.                      {  
  227.                          result = MessageBox.Show("Do you want to process this initial general ledger transaction?""Verification Mode", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);  
  228.                      }  
  229.   
  230.          if (result == DialogResult.Yes)  
  231.          {  
  232.     
  233.              // if it is a debit posting, then do this...  
  234.              if (ApplyOffSettingDebits == 1)  
  235.              {  
  236.   
  237.                  // get the date, transaction description, debit amount  
  238.                  // and the transaction type from the Winform controls.  
  239.                  // create the new posting record and then append it to  
  240.                  // the corresponding general ledger selected by the operator.  
  241.                  transaction_str = textBox_transactiondescription.Text;  
  242.                  debit_str = textBox_enteramounttobeapplied.Text;  
  243.   
  244.                  charVal_date = dateString.ToCharArray(0, dateString.Length);  
  245.                  charVal_tranaction = transaction_str.ToCharArray(0, transaction_str.Length);  
  246.                  charVal_debit = debit_str.ToCharArray(0, debit_str.Length);  
  247.   
  248.                  for (a = 0; a < GLDETAILEN - 2; a++) recordatavar_transactions[a] = (char)32;  
  249.                  for (a = 0; a < dateString.Length; a++) recordatavar_transactions[a] = charVal_date[a];  
  250.                  if (this.comboBox_transactiontype.Text == "CR")  
  251.                  {  
  252.                      recordatavar_transactions[8] = 'C';  
  253.                      recordatavar_transactions[9] = 'R';  
  254.                  }  
  255.                  if (this.comboBox_transactiontype.Text == "CD")  
  256.                  {  
  257.                      recordatavar_transactions[8] = 'C';  
  258.                      recordatavar_transactions[9] = 'D';  
  259.                  }  
  260.                  if (this.comboBox_transactiontype.Text == "GL")  
  261.                  {  
  262.                      recordatavar_transactions[8] = 'G';  
  263.                      recordatavar_transactions[9] = 'L';  
  264.                  }  
  265.                  if (this.comboBox_transactiontype.Text == "J")  
  266.                  {  
  267.                      recordatavar_transactions[8] = 'J';  
  268.                      recordatavar_transactions[9] = ' ';  
  269.                  }  
  270.                  if (this.comboBox_transactiontype.Text == "PR")  
  271.                  {  
  272.                      recordatavar_transactions[8] = 'P';  
  273.                      recordatavar_transactions[9] = 'R';  
  274.                  }  
  275.                  if (this.comboBox_transactiontype.Text == "PY")  
  276.                  {  
  277.                      recordatavar_transactions[8] = 'P';  
  278.                      recordatavar_transactions[9] = 'Y';  
  279.                  }  
  280.                  if (this.comboBox_transactiontype.Text == "ST")  
  281.                  {  
  282.                      recordatavar_transactions[8] = 'S';  
  283.                      recordatavar_transactions[9] = 'T';  
  284.                  }  
  285.                  for (a = 0; a < transaction_str.Length; a++) recordatavar_transactions[a + 10] = charVal_tranaction[a];  
  286.                  for (a = 0; a < debit_str.Length; a++) recordatavar_transactions[a + 50] = charVal_debit[a];  
  287.                  for (a = 0; a < 3; a++) recordatavar_transactions[a + 70] = charVal_auto_number[a];  
  288.   
  289.   
  290.                  FileStream fstreamobj1 = new FileStream(currdir + strfile, FileMode.Append);  
  291.                  StreamWriter writerobj1 = new StreamWriter(fstreamobj1);  
  292.                  writerobj1.WriteLine(recordatavar_transactions);  
  293.                  writerobj1.Close();  
  294.                  fstreamobj1.Close();  
  295.   
  296.              }  
  297.       
  298.              // if it is a credit posting, then do this...  
  299.              if (ApplyOffSettingCredits == 1)  
  300.              {  
  301.   
  302.                  // get the date, transaction description, credit amount  
  303.                  // and the transaction type from the Winform controls.  
  304.                  // create the new posting record and then append it to  
  305.                  // the corresponding general ledger selected by the operator.  
  306.                  transaction_str = textBox_transactiondescription.Text;  
  307.                  credit_str = textBox_enteramounttobeapplied.Text;  
  308.   
  309.                  charVal_date = dateString.ToCharArray(0, dateString.Length);  
  310.                  charVal_tranaction = transaction_str.ToCharArray(0, transaction_str.Length);  
  311.                  charVal_credit = credit_str.ToCharArray(0, credit_str.Length);  
  312.   
  313.                  for (a = 0; a < GLDETAILEN - 2; a++) recordatavar_transactions[a] = (char)32;  
  314.                  for (a = 0; a < dateString.Length; a++) recordatavar_transactions[a] = charVal_date[a];  
  315.                  if (this.comboBox_transactiontype.Text == "CR")  
  316.                  {  
  317.                      recordatavar_transactions[8] = 'C';  
  318.                      recordatavar_transactions[9] = 'R';  
  319.                  }  
  320.                  if (this.comboBox_transactiontype.Text == "CD")  
  321.                  {  
  322.                      recordatavar_transactions[8] = 'C';  
  323.                      recordatavar_transactions[9] = 'D';  
  324.                  }  
  325.                  if (this.comboBox_transactiontype.Text == "GL")  
  326.                  {  
  327.                      recordatavar_transactions[8] = 'G';  
  328.                      recordatavar_transactions[9] = 'L';  
  329.                  }  
  330.                  if (this.comboBox_transactiontype.Text == "J")  
  331.                  {  
  332.                      recordatavar_transactions[8] = 'J';  
  333.                      recordatavar_transactions[9] = ' ';  
  334.                  }  
  335.                  if (this.comboBox_transactiontype.Text == "PR")  
  336.                  {  
  337.                      recordatavar_transactions[8] = 'P';  
  338.                      recordatavar_transactions[9] = 'R';  
  339.                  }  
  340.                  if (this.comboBox_transactiontype.Text == "PY")  
  341.                  {  
  342.                      recordatavar_transactions[8] = 'P';  
  343.                      recordatavar_transactions[9] = 'Y';  
  344.                  }  
  345.                  if (this.comboBox_transactiontype.Text == "ST")  
  346.                  {  
  347.                      recordatavar_transactions[8] = 'S';  
  348.                      recordatavar_transactions[9] = 'T';  
  349.                  }  
  350.                  for (a = 0; a < transaction_str.Length; a++) recordatavar_transactions[a + 10] = charVal_tranaction[a];  
  351.                  for (a = 0; a < credit_str.Length; a++) recordatavar_transactions[a + 60] = charVal_credit[a];  
  352.                  for (a = 0; a < 3; a++) recordatavar_transactions[a + 70] = charVal_auto_number[a];  
  353.   
  354.   
  355.                  FileStream fstreamobj1 = new FileStream(currdir + strfile, FileMode.Append);  
  356.                  StreamWriter writerobj1 = new StreamWriter(fstreamobj1);  
  357.                  writerobj1.WriteLine(recordatavar_transactions);  
  358.                  writerobj1.Close();  
  359.                  fstreamobj1.Close();  
  360.   
  361.              }  
  362.       
  363.              // subtract the amount that was just posted from the remaining  
  364.              // balance and zero the amount to be applied on the screen and  
  365.              // wait for the operator to enter a new amount to be applied for  
  366.              // the next posting.  
  367.              new_remaining_balance = remaining_balance - post_amount;  
  368.   
  369.              this.textBox_enteramounttobeapplied.Text = "      0.00";  
  370.              amount_flag = 0;  
  371.   
  372.              // if the remaining balance is down to zero and the Chart of  
  373.              // Accounts listing color is tomato (offsetting side of posting  
  374.              // operation), then do this...  
  375.              if (new_remaining_balance == 0 && MakeListBoxTomato == 1)  
  376.              {  
  377.   
  378.                  // set the Chart of Accounts listing color to sandy brown.  
  379.                  this.listBox_chartofaccountslisting.BackColor = Color.SandyBrown;  
  380.                  MakeListBoxSandyBrown = 1;  
  381.                  MakeListBoxMediumPurple = 0;  
  382.                  MakeListBoxTomato = 0;  
  383.                  // blank out transaction description text box and  
  384.                  // re-enable both buttons for "total debit amount" and  
  385.                  // "total credit amount".  
  386.                  this.button_totaldebitamountfordoubleentryposting.Enabled = true;  
  387.                  this.button_totalcreditamountfordoubleentryposting.Enabled = true;  
  388.                  this.textBox_transactiondescription.Text = "";  
  389.   
  390.                  // if the initial posting was a debit, then make it a credit.  
  391.                  // if it had been a credit, then make it a debit.  
  392.                  if (ApplyOffSettingDebits == 1 && ApplyOffSettingCredits == 0)  
  393.                  {  
  394.                      ApplyOffSettingDebits = 0;  
  395.                      ApplyOffSettingCredits = 1;  
  396.                  }  
  397.                  else  
  398.                  {  
  399.                      ApplyOffSettingDebits = 1;  
  400.                      ApplyOffSettingCredits = 0;  
  401.                  }  
  402.   
  403.              }  
  404.   
  405.              // if the remaining balance is down to zero and the Chart of  
  406.              // Accounts listing color is medium purple (initial side of posting  
  407.              // operation), then do this...  
  408.              if (new_remaining_balance == 0 && MakeListBoxMediumPurple == 1)  
  409.              {  
  410.   
  411.                  // set the Chart of Accounts listing color to tomato.  
  412.                  this.listBox_chartofaccountslisting.BackColor = Color.Tomato;  
  413.                  MakeListBoxSandyBrown = 0;  
  414.                  MakeListBoxMediumPurple = 0;  
  415.                  MakeListBoxTomato = 1;  
  416.                  // set the remaining balance text box to the original amount to be  
  417.                  // posted from the initial posting operation.  
  418.                  this.textBox_remainingbalanceoftotal.Text = remaining_offsetting_balance_str;  
  419.                  amount_flag = 1;  
  420.   
  421.                  // if the initial posting was a debit, then make it a credit.  
  422.                  // if it had been a credit, then make it a debit.  
  423.                  if (ApplyOffSettingDebits == 1 && ApplyOffSettingCredits == 0)  
  424.                  {  
  425.                      ApplyOffSettingDebits = 0;  
  426.                      ApplyOffSettingCredits = 1;  
  427.                  }  
  428.                  else  
  429.                  {  
  430.                      ApplyOffSettingDebits = 1;  
  431.                      ApplyOffSettingCredits = 0;  
  432.                  }  
  433.   
  434.              }  
  435.     
  436.              // if there is still a remaining balance, then  
  437.              // show it on the Winform control.  
  438.              if (amount_flag == 0)  
  439.              {  
  440.   
  441.              for (a = 0; a < 10; a++) totalamount[a] = (char)32;  
  442.              totalamount[6] = (char)48;  
  443.              totalamount[7] = (char)46;  
  444.              totalamount[8] = (char)48;  
  445.              totalamount[9] = (char)48;  
  446.              countervar = 9;  
  447.              do  
  448.              {  
  449.                  longresult = Math.DivRem(new_remaining_balance, 10, out long2);  
  450.                  new_remaining_balance = longresult;  
  451.                  if (long2 == 0) totalamount[countervar] = (char)48;  
  452.                  if (long2 == 1) totalamount[countervar] = (char)49;  
  453.                  if (long2 == 2) totalamount[countervar] = (char)50;  
  454.                  if (long2 == 3) totalamount[countervar] = (char)51;  
  455.                  if (long2 == 4) totalamount[countervar] = (char)52;  
  456.                  if (long2 == 5) totalamount[countervar] = (char)53;  
  457.                  if (long2 == 6) totalamount[countervar] = (char)54;  
  458.                  if (long2 == 7) totalamount[countervar] = (char)55;  
  459.                  if (long2 == 8) totalamount[countervar] = (char)56;  
  460.                  if (long2 == 9) totalamount[countervar] = (char)57;  
  461.                  countervar--;  
  462.                  if (countervar == 7)  
  463.                  {  
  464.                      totalamount[countervar] = (char)46;  
  465.                      countervar--;  
  466.                  }  
  467.              } while (new_remaining_balance > 0);  
  468.   
  469.                  this.textBox_remainingbalanceoftotal.Text = new string(totalamount);  
  470.              }  
  471.   
  472.   
  473.          }  
  474.     
  475.                  }  
  476.                  else  
  477.                  {  
  478.     
  479.                      MessageBox.Show("The amount you want to post is greater than the remaining balance...transaction aborted....please input a new posting amount and retry...""Error Mode");  
  480.     
  481.                  }  
  482.     
  483.              }  
  484.          
  485.     
  486.          }  
  487.   
  488.      }  
CONCLUSION

This method of performing a double entry posting is versatile, because the total debit or credit amount to be posted can be spread among any number of general ledger accounts until the total amount has been subtracted down to zero by the program’s built in calculator. It is also user friendly, because the color coded listing for the Chart of Accounts uses specific colors to denote the initial posting phase of “medium purple” and the offsetting posting phase of “tomato”. I have seen Chart of Accounts software packages that are very intimidating to work with. I tried to get as far away from that as I could when I designed this one.