Introduction

This is the second method I created for performing a double entry posting to Chart Of Accounts. The first one involved “coloring” the Chart Of Accounts listing displayed in the Windows form to discern the difference between the initial postings and the offsetting postings to the user. That was my own idea for making the double entry posting for the application and it worked well, but the customer had another idea. It was based on how he manually performed double entry postings with pen and paper. His idea is also very good and it will be the subject of this article.

Here's my first article: C# Code For Making a Double Entry General Ledger Posting - Method 1

Moving Forward

Figure 1 is the pop up menu from this program for performing double entry postings to Chart Of Accounts. The option titled, “Add And Remove Double Entry Postings” has already been described in the article I wrote by the same name as this one for “Method 1”. “Add And Remove General Ledgers” is for adding and removing general ledgers from Chart Of Accounts. It does not involve the double entry posting process.

General Ledgers
Figure 1

The other options described as “CD Ledgers Maintenance” (cash disbursements), “CR Ledgers Maintenance” (cash receipts), “GL Ledgers Maintenance” (general ledger), “J Ledgers Maintenance” (journal entry), “PR Ledgers Maintenance” (payroll) and “ST Ledgers Maintenance” (standard transaction) are double entry posting utilities, which are the subject of this article. In terms of programming, they are all mechanically identical, though the listing of general ledgers within each of these utilities differs. For the purpose of not being redundant, I will describe in detail the functions of the “CD Ledgers Maintenance” Windows form.

A description of the initial posting procedure,

description of the initial posting
Figure 2

A listing of pre-determined general ledger accounts along with their DR (debit) and CR (credit) columns showing the total debit and credit amounts to be posted to each account are displayed in a list box above in Figure 2. The text boxes located directly below are for entering debit and credit amounts. When you enter an amount in either or both of two text boxes and then click the “Post The Debit And/Or Credit Amounts Entered For The Highlighted GL#” button immediately to the right, the program will post the debit and credit amount(s) entered in the corresponding column in whatever general ledger account in the list box you had previously highlighted with the mouse. There is also a “Yes or No” dropdown for adding the entered amount(s) to the previous fiscal year if desired. And there is a text box for allowing the user to override the current date for this transaction with an alternate date to be entered by the user (the current date is auto entered by default upon loading the form). Figures 3, 4 and 5 below illustrate the initial posting procedure.

Select data
Figure 3

Verification Mode
Figure 4

table
Figure 5


We have not actually posted to the Chart Of Accounts yet. These postings are only being added to a sort of staging area as a list box on the Windows form. Here is the C# code that details how the “Post The Debit And/Or Credit Amounts Entered For The Highlighted GL#” button works:
  1. private void PostTheAmount(object sender, EventArgs e)
  2. {
  3. // declare local variables.
  4. string listBox1_String, debit_str, credit_str, previousfiscal;
  5. char[] charVal_debit, charVal_credit, charVal_date;
  6. // get current working directory.
  7. currdir = Directory.GetCurrentDirectory();
  8. currdir = currdir.Substring(0, currdir.Length - 9);
  9. // verify that a ledger has been selected from the Chart Of Accounts
  10. // listing before proceeding.
  11. if (listBox1.SelectedIndex != -1)
  12. {
  13. // grab the selected general ledger from the Windows form into
  14. // a string variable, 'listBox1_String'.
  15. listBox1_String = listBox1.Text;
  16. // if the general ledger that was selected is invalid, then
  17. // display a message for this, then abort.
  18. if (listBox1_String.Substring(0, 1) == "-" || listBox1_String.Substring(0, 1) == "G") MessageBox.Show("Invalid selection...", "Error Mode");
  19. // if the general ledger that was selected is valid, then proceed.
  20. if (listBox1_String.Substring(0, 1) != "-" && listBox1_String.Substring(0, 1) != "G")
  21. {
  22. result = MessageBox.Show("Do you want to post the debit and/or credit amount(s) to this highlighted general ledger?", "Verification Mode", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
  23. if (result == DialogResult.Yes)
  24. {
  25. // grab the Windows form flag for whether or not to add these
  26. // entered amount(s) to the previous fiscal year.
  27. previousfiscal = this.addtoprevfiscal.Text;
  28. // grab the debit and credit amount(s) and convert to character arrays
  29. // to prepare for further processing.
  30. debit_str = debitAmount.Text;
  31. credit_str = creditAmount.Text;
  32. charVal_debit = debit_str.ToCharArray(0, debit_str.Length);
  33. charVal_credit = credit_str.ToCharArray(0, credit_str.Length);
  34. // open a file stream to the Chart Of Accounts data file for
  35. // subsequent read operations.
  36. FileInfo datafileinfo = new FileInfo(currdir + "mastcoa.txt");
  37. sizeofdatafile = datafileinfo.Length;
  38. StreamReader streamobj = new StreamReader(currdir + "mastcoa.txt");
  39. streamobj.BaseStream.Seek(0, SeekOrigin.Begin);
  40. // initialize the Chart Of Accounts data file offset to 0.
  41. datafileoffset = 0;
  42. do
  43. {
  44. // read the next sequential record from the Chart Of Accounts data file.
  45. stringVal = streamobj.ReadLine();
  46. // construct a transient general ledger file name for the current Chart
  47. // Of Accounts record and assign it to the variable, 'strfile_temp'.
  48. strfile_temp = stringVal.Substring(45, 8) + "_.txt";
  49. // compare the general ledger # from the 'stringVal' variable to what was
  50. // selected in the listing on the Windows form. if equal, then proceed with
  51. // the posting of the entered amount(s) to the Windows form.
  52. if (stringVal.Substring(41, 4) == listBox1_String.Substring(0, 4))
  53. {
  54. // clear out the character array, 'recordatavar_transactions', used
  55. // for the Windows form posting operation.
  56. for (a = 0; a < GLDETAILEN - 2; a++) recordatavar_transactions[a] = (char)32;
  57. // assign whatever debit and/or credit amount(s) were entered into the
  58. // Windows form to the character array, 'recordatavar_transactions'.
  59. for (a = 0; a < debit_str.Length; a++) recordatavar_transactions[a + 50] = charVal_debit[a];
  60. for (a = 0; a < credit_str.Length; a++) recordatavar_transactions[a + 60] = charVal_credit[a];
  61. // grab the date of the alternate date field and assign
  62. // it to the variable for the transaction date, 'dateString'.
  63. dateString = NewXctionDate.Text;
  64. // if no date was entered in the alternate date field, then assign the
  65. // current date to 'dateString'.
  66. if (dateString.Length < 8)
  67. {
  68. DateTime saveNow = DateTime.Now;
  69. dateString = saveNow.ToString(datePatt);
  70. }
  71. // convert 'dateString' to a character array and insert it into the
  72. // character array 'recordatavar_transactions', which also holds any
  73. // debit and/or credit amount(s) entered by the user.
  74. charVal_date = dateString.ToCharArray(0, dateString.Length);
  75. for (a = 0; a < dateString.Length; a++) recordatavar_transactions[a] = charVal_date[a];
  76. // if the user chose to add these debit and/or credit amount(s) to the
  77. // previous fiscal year, then use the '^' symbol to denote that in the
  78. // character array, 'recordatavar_transactions'.
  79. if (previousfiscal == "Yes")
  80. {
  81. recordatavar_transactions[2] = '^';
  82. }
  83. // append the character array, 'recordatavar_transactions', to the
  84. // transient data file specified by 'strfile_temp'.
  85. FileStream fstreamobj1 = new FileStream(currdir + strfile_temp, FileMode.Append);
  86. StreamWriter writerobj1 = new StreamWriter(fstreamobj1);
  87. writerobj1.WriteLine(recordatavar_transactions);
  88. writerobj1.Close();
  89. fstreamobj1.Close();
  90. }
  91. // advance the Chart Of Accounts data file offset forward by one
  92. // record to the next sequentially located record.
  93. datafileoffset = datafileoffset + GLMASTERLEN;
  94. } while (datafileoffset < sizeofdatafile);
  95. // close the Chart Of Accounts data file stream.
  96. streamobj.Close();
  97. // repaint the Windows form to reflect the changes.
  98. UpdateListing();
  99. }
  100. }
  101. }
  102. else
  103. {
  104. MessageBox.Show("No general ledger selection was made...please try again.", "Error Mode");
  105. }
  106. }
Adding supplemental general ledger accounts to the initial posting process

This next part will discuss the coding I use to add supplemental general ledger accounts to those ledger accounts displayed in the list box by default. This is a flexible feature that allows the user to add as many as 4 ledgers that may need to be incorporated into the initial posting process for any number of reasons. Here is the code that details how the “Add A Supplemental GL Account To The Current List” button functions:
  1. private void AddSupplementalGL(object sender, EventArgs e)
  2. {
  3. // declare local variables.
  4. int found_glno;
  5. long sizeofdatafile_supplemental;
  6. string glno_str, glname_str;
  7. char[] charVal_glno, charVal_glname;
  8. result = MessageBox.Show("Do you want to add a supplemental GL account to the current listing?", "Verification Mode", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
  9. if (result == DialogResult.Yes)
  10. {
  11. // get the file size of the supplemental cash disbursements
  12. // data file, 'cd_ledger.txt'.
  13. FileInfo datafileinfo_supplemental = new FileInfo(currdir + "cd_ledger.txt");
  14. sizeofdatafile_supplemental = datafileinfo_supplemental.Length;
  15. // if the number of added supplemental general ledgers
  16. // for the current session is less than 5, then proceed.
  17. if (sizeofdatafile_supplemental < GLAUXILIARY * 5)
  18. {
  19. // get the user entered supplemental general ledger # to add to
  20. // the Windows form listing.
  21. glno_str = AuxiliaryGLNo.Text;
  22. // if the length of the user entered supplemental general
  23. // ledger # is 4, then proceed.
  24. if (glno_str.Length == 4)
  25. {
  26. // open a file stream to the Chart Of Accounts data file for
  27. // subsequent read operations.
  28. FileInfo datafileinfo = new FileInfo(currdir + "mastcoa.txt");
  29. sizeofdatafile = datafileinfo.Length;
  30. StreamReader streamobj = new StreamReader(currdir + "mastcoa.txt");
  31. streamobj.BaseStream.Seek(0, SeekOrigin.Begin);
  32. // initialize the Chart Of Accounts data file offset to 0.
  33. // set the 'found_glno' flag to its default of 0 to indicate
  34. // the general ledger # to search for is not yet found.
  35. datafileoffset = 0;
  36. found_glno = 0;
  37. do
  38. {
  39. // read the next sequential record from the Chart Of Accounts data file.
  40. stringVal = streamobj.ReadLine();
  41. // if the user entered general ledger # has been matched in the Chart Of
  42. // Accounts data file, then proceed.
  43. if (stringVal.Substring(41, 4) == glno_str)
  44. {
  45. // set the 'found_glno' flag to 1 to denote the user
  46. // entered general ledger # has been matched.
  47. found_glno = 1;
  48. // construct a transient copy the corresponding general
  49. // ledger filename from the Chart Of Accounts record and
  50. // assign it to the variable, 'strfile_temp'.
  51. strfile_temp = stringVal.Substring(45, 8) + "_.txt";
  52. // check to see if this transient general ledger filename
  53. // already exists and if so, get rid of it.
  54. if (File.Exists(currdir + strfile_temp))
  55. {
  56. File.Delete(currdir + strfile_temp);
  57. }
  58. // clear out the character array, 'recordatavar_transactions',
  59. // used for the supplemental general ledger file addition to the Windows form.
  60. for (a = 0; a < GLDETAILEN - 2; a++) recordatavar_transactions[a] = (char)32;
  61. // open a file stream to transient general ledger account filename specified
  62. // by the user and then write the 'recordatavar_transactions' character
  63. // array to it.
  64. FileStream fstreamobj1 = new FileStream(currdir + strfile_temp, FileMode.Create);
  65. StreamWriter writerobj1 = new StreamWriter(fstreamobj1);
  66. writerobj1.WriteLine(recordatavar_transactions);
  67. writerobj1.Close();
  68. fstreamobj1.Close();
  69. // add the supplemental general ledger # entered by the user as well as its
  70. // descriptive name to character arrays.
  71. charVal_glno = glno_str.ToCharArray(0, glno_str.Length);
  72. glname_str = stringVal.Substring(0, 41);
  73. charVal_glname = glname_str.ToCharArray(0, glname_str.Length);
  74. // add the above 2 items to the 'recordatavar_aux_ledger' character array.
  75. for (a = 0; a < 45; a++) recordatavar_aux_ledger[a] = (char)32;
  76. for (a = 0; a < 4; a++) recordatavar_aux_ledger[a] = charVal_glno[a];
  77. for (a = 0; a < 41; a++) recordatavar_aux_ledger[a + 4] = charVal_glname[a];
  78. // open a file stream to the supplemental cash disbursements data file,
  79. // and append the 'recordatavar_aux_ledger' character array to it.
  80. FileStream fstreamobj2 = new FileStream(currdir + "cd_ledger.txt", FileMode.Append);
  81. StreamWriter writerobj2 = new StreamWriter(fstreamobj2);
  82. writerobj2.WriteLine(recordatavar_aux_ledger);
  83. writerobj2.Close();
  84. fstreamobj2.Close();
  85. }
  86. // advance the Chart Of Accounts data file offset forward by one
  87. // record to the next sequentially located record.
  88. datafileoffset = datafileoffset + GLMASTERLEN;
  89. } while (datafileoffset < sizeofdatafile && found_glno == 0);
  90. // close the Chart Of Accounts data file stream.
  91. streamobj.Close();
  92. // reset the supplemental general ledger # control on the Windows form to blank.
  93. this.AuxiliaryGLNo.Text = "";
  94. // repaint the Windows form to reflect the changes.
  95. UpdateListing();
  96. if (found_glno == 0)
  97. {
  98. MessageBox.Show("The GL number was not found and was not added to the current listing...please try again.", "Error Mode");
  99. }
  100. }
  101. else
  102. {
  103. MessageBox.Show("Invalid GL number...please try again.", "Error Mode");
  104. }
  105. }
  106. else
  107. {
  108. MessageBox.Show("Unable to add any more supplemental GL accounts...", "Error Mode");
  109. }
  110. }
  111. }
Verify the amounts before posting to chart of accounts

When you scroll to the bottom of the list box on the Windows form, you will see grand totals at the bottom. This is a convenience that tells the user if the debits and credits are equal (in balance and ready for posting to Chart Of Accounts). See the following figure 6,

Verify the amounts
Figure 6

Post the displayed amounts in the list box to chart of accounts


The last step is to post the amounts from the list box on the Windows form to Chart Of Accounts. Click the button, “Append The Displayed Amounts To Their Ledgers”, to perform this task (see Figure 7).

Post the displayed
Figure 7

The code for this operation is shown here:
  1. private void PostToChartOfAccounts(object sender, EventArgs e)
  2. {
  3. // declare local variables.
  4. string stringAutoNumber, strfile_orig, transaction_str;
  5. long autonum_var;
  6. char[] charVal_auto_number = new char[3];
  7. char[] put_in_orig_ledger, charVal_tranaction;
  8. // get current working directory.
  9. currdir = Directory.GetCurrentDirectory();
  10. currdir = currdir.Substring(0, currdir.Length - 9);
  11. result = MessageBox.Show("Do you want to proceed with this permanent double entry posting transaction for all the general ledgers displayed?", "Verification Mode", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
  12. if (result == DialogResult.Yes)
  13. {
  14. Cursor.Current = new Cursor(currdir + "Busy_l.cur");
  15. // auto generate the next general ledger transaction number in sequence
  16. // to be included with the permananet general ledger postings to be used
  17. // for future operations and save this in a small data file, 'autonumber.txt'.
  18. StreamReader streamobj3 = new StreamReader(currdir + "autonumber.txt");
  19. streamobj3.BaseStream.Seek(0, SeekOrigin.Begin);
  20. stringAutoNumber = streamobj3.ReadLine();
  21. streamobj3.Close();
  22. for (a = 0; a < 3; a++)
  23. {
  24. convert_to_number[a] = 0;
  25. if (stringAutoNumber.Substring(a, 1) == "0") convert_to_number[a] = 0;
  26. if (stringAutoNumber.Substring(a, 1) == "1") convert_to_number[a] = 1;
  27. if (stringAutoNumber.Substring(a, 1) == "2") convert_to_number[a] = 2;
  28. if (stringAutoNumber.Substring(a, 1) == "3") convert_to_number[a] = 3;
  29. if (stringAutoNumber.Substring(a, 1) == "4") convert_to_number[a] = 4;
  30. if (stringAutoNumber.Substring(a, 1) == "5") convert_to_number[a] = 5;
  31. if (stringAutoNumber.Substring(a, 1) == "6") convert_to_number[a] = 6;
  32. if (stringAutoNumber.Substring(a, 1) == "7") convert_to_number[a] = 7;
  33. if (stringAutoNumber.Substring(a, 1) == "8") convert_to_number[a] = 8;
  34. if (stringAutoNumber.Substring(a, 1) == "9") convert_to_number[a] = 9;
  35. }
  36. autonum_var = ((convert_to_number[0] * 100) + (convert_to_number[1] * 10) + (convert_to_number[2] * 1));
  37. autonum_var++;
  38. if (autonum_var > 999)
  39. {
  40. autonum_var = 0;
  41. }
  42. for (a = 0; a < 3; a++) charVal_auto_number[a] = (char)48;
  43. countervar = 2;
  44. do
  45. {
  46. longresult = Math.DivRem(autonum_var, 10, out long2);
  47. autonum_var = longresult;
  48. if (long2 == 0) charVal_auto_number[countervar] = (char)48;
  49. if (long2 == 1) charVal_auto_number[countervar] = (char)49;
  50. if (long2 == 2) charVal_auto_number[countervar] = (char)50;
  51. if (long2 == 3) charVal_auto_number[countervar] = (char)51;
  52. if (long2 == 4) charVal_auto_number[countervar] = (char)52;
  53. if (long2 == 5) charVal_auto_number[countervar] = (char)53;
  54. if (long2 == 6) charVal_auto_number[countervar] = (char)54;
  55. if (long2 == 7) charVal_auto_number[countervar] = (char)55;
  56. if (long2 == 8) charVal_auto_number[countervar] = (char)56;
  57. if (long2 == 9) charVal_auto_number[countervar] = (char)57;
  58. countervar--;
  59. } while (autonum_var > 0);
  60. if (File.Exists(currdir + "autonumber.txt"))
  61. {
  62. File.Delete(currdir + "autonumber.txt");
  63. }
  64. FileStream fstreamobj2 = new FileStream(currdir + "autonumber.txt", FileMode.Create);
  65. StreamWriter writerobj2 = new StreamWriter(fstreamobj2);
  66. writerobj2.WriteLine(charVal_auto_number);
  67. writerobj2.Close();
  68. fstreamobj2.Close();
  69. // open a file stream to the Chart Of Accounts data file for
  70. // subsequent read operations.
  71. FileInfo datafileinfo = new FileInfo(currdir + "mastcoa.txt");
  72. sizeofdatafile = datafileinfo.Length;
  73. StreamReader streamobj = new StreamReader(currdir + "mastcoa.txt");
  74. streamobj.BaseStream.Seek(0, SeekOrigin.Begin);
  75. // open a file stream to the supplemental cash disbursements data file,
  76. // 'cd_ledger.txt', for subsequent read operations.
  77. FileInfo datafileinfo_auxiliary = new FileInfo(currdir + "cd_ledger.txt");
  78. sizeofdatafile_auxiliary = datafileinfo_auxiliary.Length;
  79. StreamReader streamobj_auxiliary = new StreamReader(currdir + "cd_ledger.txt");
  80. // initialize the Chart Of Accounts data file offset to 0.
  81. datafileoffset = 0;
  82. do
  83. {
  84. // read the next sequential record from the Chart Of Accounts data file.
  85. stringVal = streamobj.ReadLine();
  86. // extract the transient general ledger file name from the just read
  87. // Chart Of Accounts record and assign it to the transient general ledger
  88. // filename, 'strfile_temp'.
  89. strfile_temp = stringVal.Substring(45, 8);
  90. strfile_temp = strfile_temp + "_.txt";
  91. // extract the permanent general ledger file name from the just read
  92. // Chart Of Accounts record and assign it to the permanent general ledger
  93. // filename, 'strfile_orig'.
  94. strfile_orig = stringVal.Substring(45, 8);
  95. strfile_orig = strfile_orig + ".txt";
  96. // match the general ledger # of the current record from the Chart Of
  97. // Accounts data file stream to one of those from the listing
  98. // in the Windows form and set a flag, 'calc_flag', upon matching it.
  99. calc_flag = 0;
  100. if (stringVal.Substring(41, 4) == "1000")
  101. {
  102. calc_flag = 1;
  103. }
  104. if (stringVal.Substring(41, 4) == "1010")
  105. {
  106. calc_flag = 1;
  107. }
  108. if (stringVal.Substring(41, 4) == "1040")
  109. {
  110. calc_flag = 1;
  111. }
  112. if (stringVal.Substring(41, 4) == "1070")
  113. {
  114. calc_flag = 1;
  115. }
  116. if (stringVal.Substring(41, 4) == "1080")
  117. {
  118. calc_flag = 1;
  119. }
  120. if (stringVal.Substring(41, 4) == "2100")
  121. {
  122. calc_flag = 1;
  123. }
  124. if (stringVal.Substring(41, 4) == "2110")
  125. {
  126. calc_flag = 1;
  127. }
  128. if (stringVal.Substring(41, 4) == "2120")
  129. {
  130. calc_flag = 1;
  131. }
  132. if (stringVal.Substring(41, 4) == "2160")
  133. {
  134. calc_flag = 1;
  135. }
  136. if (stringVal.Substring(41, 4) == "2210")
  137. {
  138. calc_flag = 1;
  139. }
  140. if (stringVal.Substring(41, 4) == "2400")
  141. {
  142. calc_flag = 1;
  143. }
  144. if (stringVal.Substring(41, 4) == "3030")
  145. {
  146. calc_flag = 1;
  147. }
  148. if (stringVal.Substring(41, 4) == "4200")
  149. {
  150. calc_flag = 1;
  151. }
  152. if (stringVal.Substring(41, 4) == "4400")
  153. {
  154. calc_flag = 1;
  155. }
  156. if (stringVal.Substring(41, 4) == "5000")
  157. {
  158. calc_flag = 1;
  159. }
  160. if (stringVal.Substring(41, 4) == "6500")
  161. {
  162. calc_flag = 1;
  163. }
  164. if (stringVal.Substring(41, 4) == "7300")
  165. {
  166. calc_flag = 1;
  167. }
  168. if (stringVal.Substring(41, 4) == "7400")
  169. {
  170. calc_flag = 1;
  171. }
  172. if (stringVal.Substring(41, 4) == "8200")
  173. {
  174. calc_flag = 1;
  175. }
  176. if (stringVal.Substring(41, 4) == "8300")
  177. {
  178. calc_flag = 1;
  179. }
  180. if (stringVal.Substring(41, 4) == "9100")
  181. {
  182. calc_flag = 1;
  183. }
  184. // attempt to match the general ledger # of the current record from the Chart Of
  185. // Accounts to any of the general ledger #'s in the supplemental cash disbursements
  186. // data file, and set a flag, 'calc_flag', upon matching it.
  187. streamobj_auxiliary.BaseStream.Seek(0, SeekOrigin.Begin);
  188. datafileoffset_auxiliary = 0;
  189. do
  190. {
  191. stringVal_auxiliary = streamobj_auxiliary.ReadLine();
  192. if (stringVal.Substring(41, 4) == stringVal_auxiliary.Substring(0, 4))
  193. {
  194. calc_flag = 1;
  195. auxiliary_ledger_count++;
  196. }
  197. datafileoffset_auxiliary = datafileoffset_auxiliary + GLAUXILIARY;
  198. } while (datafileoffset_auxiliary < sizeofdatafile_auxiliary);
  199. // if the general ledger # of the current record from the Chart Of
  200. // Accounts has been matched and the transient general ledger file,
  201. // 'strfile_temp', does exist, then proceed.
  202. if (calc_flag == 1 && File.Exists(currdir + strfile_temp))
  203. {
  204. // open a file stream to the transient general ledger file,
  205. // 'strfile_temp', for subsequent read operations.
  206. FileInfo datafileinfo2 = new FileInfo(currdir + strfile_temp);
  207. sizeofdatafile2 = datafileinfo2.Length;
  208. StreamReader streamobj2 = new StreamReader(currdir + strfile_temp);
  209. streamobj2.BaseStream.Seek(0, SeekOrigin.Begin);
  210. // initialize the transient general ledger filename, 'strfile_temp', offset to 0.
  211. datafileoffset2 = 0;
  212. do
  213. {
  214. // read a sequential record from the transient general ledger data file.
  215. stringVal = streamobj2.ReadLine();
  216. // if there are a debit and/or credit amount(s) in the 'stringVal' variable,
  217. // then proceed with appending the amount(s) to the permanent general ledger
  218. // data file.
  219. if (stringVal.Substring(50, 10) != " " || stringVal.Substring(60, 10) != " ")
  220. {
  221. // set the transaction description to 'CD Transaction' and convert it to a
  222. // character array. assign the current record from the transient general ledger
  223. // data file, 'strfile_temp', to a character array.
  224. transaction_str = "CD Transaction";
  225. charVal_tranaction = transaction_str.ToCharArray(0, transaction_str.Length);
  226. put_in_orig_ledger = stringVal.ToCharArray(0, stringVal.Length);
  227. // clear out the character array used for the posting operation to the permanent
  228. // general ledger data file.
  229. for (a = 0; a < GLDETAILEN - 2; a++) recordatavar_transactions[a] = (char)32;
  230. // assign record from the transient general ledger data file to the
  231. // 'recordatavar_transactions' character array as well as 'CD' for
  232. // the transaction type and the transaction description and also the
  233. // auto generated transaction number.
  234. for (a = 0; a < stringVal.Length; a++) recordatavar_transactions[a] = put_in_orig_ledger[a];
  235. recordatavar_transactions[8] = 'C';
  236. recordatavar_transactions[9] = 'D';
  237. for (a = 0; a < transaction_str.Length; a++) recordatavar_transactions[a + 10] = charVal_tranaction[a];
  238. for (a = 0; a < 3; a++) recordatavar_transactions[a + 70] = charVal_auto_number[a];
  239. // append the above mentioned data in the 'recordatavar_transactions' character array
  240. // to the permanent general ledger file.
  241. FileStream fstreamobj1 = new FileStream(currdir + strfile_orig, FileMode.Append);
  242. StreamWriter writerobj1 = new StreamWriter(fstreamobj1);
  243. writerobj1.WriteLine(recordatavar_transactions);
  244. writerobj1.Close();
  245. fstreamobj1.Close();
  246. }
  247. // advance the supplemental cash disbursements data file offset forward by one
  248. // record to the next sequentially located record.
  249. datafileoffset2 = datafileoffset2 + GLDETAILEN;
  250. } while (datafileoffset2 < sizeofdatafile2);
  251. // close the file stream for the transient general ledger data file.
  252. streamobj2.Close();
  253. // if the transient general ledger data file exists,
  254. // then get rid of it since it is no longer needed.
  255. if (File.Exists(currdir + strfile_temp))
  256. {
  257. File.Delete(currdir + strfile_temp);
  258. }
  259. }
  260. // advance the Chart Of Accounts data file offset forward by one
  261. // record to the next sequentially located record.
  262. datafileoffset = datafileoffset + GLMASTERLEN;
  263. } while (datafileoffset < sizeofdatafile);
  264. // close the file stream for the supplemental cash disbursements data file.
  265. streamobj_auxiliary.Close();
  266. // close the Chart Of Accounts data file stream.
  267. streamobj.Close();
  268. // if the supplemental cash disbursements data file exists, then
  269. // get rid of it and recreate a new one with a blank record.
  270. if (File.Exists(currdir + "cd_ledger.txt"))
  271. {
  272. File.Delete(currdir + "cd_ledger.txt");
  273. for (a = 0; a < 45; a++) recordatavar_aux_ledger[a] = (char)32;
  274. FileStream fstreamobj_auxiliary = new FileStream(currdir + "cd_ledger.txt", FileMode.Create);
  275. StreamWriter writerobj_auxiliary = new StreamWriter(fstreamobj_auxiliary);
  276. writerobj_auxiliary.WriteLine(recordatavar_aux_ledger);
  277. writerobj_auxiliary.Close();
  278. fstreamobj_auxiliary.Close();
  279. }
  280. // repaint the Windows form to reflect the changes.
  281. UpdateListing();
  282. Cursor.Current = Cursors.Default;
  283. }
  284. }
Conclusion

Although my first method worked well and I thought it was relatively easy to use, it still wasn’t acceptable to the customer. I have spent years learning this reality. That’s why it is always important to listen to what customers really want and cater to that want with software that will keep them happy. Just because something looks good on the drawing board doesn’t necessarily guarantee people will be satisfied with it, even if it does work correctly. Most people don’t realize just how subjective this business can be - it isn’t like going out and selling 10,000 widgets. That’s why it’s called custom software.