トップ回答者
印刷時に、前頁の小計金額を次ページの繰り越し行に正しく表示できず困っています

質問
-
zen73です。今年もどうぞよろしくお願いします。
以前につくったアプリケーションの不具合を解消したいと思っています。
DataGridViewのデータを3ページに分けて印刷しようとしています。
trapemiyaさんに教えていただいて、完成と思っていたのですが
私の点検が甘く下記のような不具合が生じております。
年をとるのは悲しいもので、半年前に書いた自分のコードすらが理解できずに
困り果てています。ぜひともお助け願います。
<DataGridViewのデータ>
月 日 大科目 小科目 適用 伝票 入金 出金 残高
4 1 会費 会費 No1 10,000 10,000
4 2 予備費 予備費 No2 1,501 8,499
4 3 総務部 会議費 No3 1,100 7,399
5 1 会費 会費 No4 15,000 22.399
5 2 予備費 予備費 No5 209 22,190
6 1 会費 会費 No6 7,000 29,190
6 2 予備費 予備費 No7 1,190 28,000
<これを印刷すると次のようになってしまいます>
--------- 1ページめ --------------------------------------------------------------------
月 日 大科目 小科目 適用 伝票 入金 出金 残高
4 1 会費 会費 No1 10,000 10,000
4 2 予備費 予備費 No2 1,501 8,499
4 3 総務部 会議費 No3 1,100 7,399
小計 10,000 2,501 7,399
--------- 2ページめ --------------------------------------------------------------------
月 日 大科目 小科目 適用 伝票 入金 出金 残高
前ページより 42,000 6,601 35,399
5 1 会費 会費 No4 15,000 22.399
5 2 予備費 予備費 No5 209 22,190
小計 57,000 6,810 50,190
--------- 3ページめ --------------------------------------------------------------------
月 日 大科目 小科目 適用 伝票 入金 出金 残高
前ページより 89,000 10,810 78,190
6 1 会費 会費 No6 7,000 29,190
6 2 予備費 予備費 No7 1,190 28,000
小計 96,000 12,000 84,000
--------- 4ページめ --------------------------------------------------------------------
月 日 大科目 小科目 適用 伝票 入金 出金 残高
前ページより 128,000 16,000 112,000
合計 128,000 16,000 112,000
Code Snippetusing System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;namespace a_book
{
public partial class frm2SuitoPrt : Form
{
//印刷データ
private string[,] hyoji = new string[500, 9];
private int rowCnt = 0;
private int page = 1;
//改ページ変数
int rnum;
int maxRow = 4;
int idx = 0;
private int[] sLen = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
private int[] strLen = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
private int[] sum = new int[] { 0, 0, 0, 0, 0, 0, 0, 0, 0 };public frm2SuitoPrt()
{
InitializeComponent();
}//frm0Menuの変数値を参照する
public frm0Menu frmMain;private void frm2SuitoPrt_Load(object sender, EventArgs e)
{
// データを 'suitoPrtDataSet.suito' テーブルに読み込む。
this.suitoTableAdapter.Fill(this.suitoPrtDataSet.suito);
//フォームの大きさを画面の解像度に合わせる
this.Width = Screen.GetWorkingArea(this).Width - 5;
this.Height = Screen.GetWorkingArea(this).Height - 2;
this.Location = new Point(2, 2);
//コントロールの配置位置調整
btnPrint.Left = suitoDataGridView.Left;
btnMenu.Left = suitoDataGridView.Right - btnMenu.Width;//ソート機能を無効にする
for (int i = 0; i < 9; i++)
{
suitoDataGridView.Columns.SortMode = DataGridViewColumnSortMode.NotSortable;
}suitoDataGridView.CurrentCell = null;
}private void setArray(int i)
{
hyoji[i + idx + 1, 0] = "";
hyoji[i + idx + 1, 1] = "";
hyoji[i + idx + 1, 2] = "";
hyoji[i + idx + 1, 3] = "";
hyoji[i + idx + 1, 4] = "次頁へ繰越";
hyoji[i + idx + 1, 5] = "小計";
hyoji[i + idx + 1, 6] = sum.ToString("#,###").PadLeft(10);
hyoji[i + idx + 1, 7] = sum[7].ToString("#,###").PadLeft(10);
hyoji[i + idx + 1, 8] = (sum- sum[7]).ToString("#,###").PadLeft(10);
hyoji[i + idx + 2, 0] = "";
hyoji[i + idx + 2, 1] = "";
hyoji[i + idx + 2, 2] = "";
hyoji[i + idx + 2, 3] = "";
hyoji[i + idx + 2, 4] = "前頁より繰越";
hyoji[i + idx + 2, 5] = "";
hyoji[i + idx + 2, 6] = sum.ToString("#,###").PadLeft(10);
hyoji[i + idx + 2, 7] = sum[7].ToString("#,###").PadLeft(10);
hyoji[i + idx + 2, 8] = (sum- sum[7]).ToString("#,###").PadLeft(10);
}
private void setHyoji(int i, int j)
{
int iVal;
if (suitoDataGridView[j + 1, i].Value != DBNull.Value)
{
iVal = Convert.ToInt32(suitoDataGridView[j + 1, i].Value);
hyoji[i + idx, j] = iVal.ToString("#,###").PadLeft(10);
sum[j] += iVal;
}
else
{
hyoji[i + idx, j] = suitoDataGridView[j + 1, i].Value.ToString();
}
}
private void leftPad(int i, int j)
{
hyoji[i + idx, j] = suitoDataGridView[j + 1, i].Value.ToString().PadLeft(2);
}
private void btnPrint_Click(object sender, EventArgs e)
{
//----------------------------------------------------
//// VS PreviewDialog ///////////////
//PrintPreviewDialog prv = new PrintPreviewDialog();
//prv.Document = printDocument1;
//prv.Width = 500;
//prv.Height = 500;
//prv.ShowDialog();
//----------------------------------------------------
//// CanonPrintDialog ///////////////
System.Drawing.Printing.PrintDocument pd =
new System.Drawing.Printing.PrintDocument();
pd.PrintPage +=
new System.Drawing.Printing.PrintPageEventHandler(printDocument1_PrintPage);
PrintDialog pdlg = new PrintDialog();
pdlg.Document = printDocument1;
if (pdlg.ShowDialog() == DialogResult.OK)
printDocument1.Print();
}private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
int i;
int num = 0;
idx = 0;
Encoding sjisEnc = Encoding.GetEncoding("Shift_JIS");
rowCnt = suitoDataGridView.RowCount - 1;
for (i = 0; i < rowCnt; i++)
{
for (int j = 0; j < 9; j++)
{
switch (j)
{
case 0:
leftPad(i, j);
break;
case 1:
leftPad(i, j);
break;
case 6:
case 7:
case 8:
setHyoji(i, j);
break;
default:
hyoji[i + idx, j] = suitoDataGridView[j + 1, i].Value.ToString();
break;
}
//文字列の長さ(Byte単位)
num = sjisEnc.GetByteCount(hyoji[i + idx, j]);
if (sLen[j] < num) sLen[j] = num;
if (strLen[j] < hyoji[i + idx, j].Length) strLen[j] = hyoji[i + idx, j].Length;
}if (i != 0 && (i % (maxRow - 2) == 0))
{
setArray(i);
idx += 2;
}
}
hyoji[i + idx, 0] = "";
hyoji[i + idx, 1] = "";
hyoji[i + idx, 2] = "";
hyoji[i + idx, 3] = "";
hyoji[i + idx, 4] = "合 計";
hyoji[i + idx, 5] = "";
hyoji[i + idx, 6] = sum.ToString("#,###").PadLeft(10);
hyoji[i + idx, 7] = sum[7].ToString("#,###").PadLeft(10);
hyoji[i + idx, 8] = (sum- sum[7]).ToString("#,###").PadLeft(10);
//増やした列数
rowCnt += idx + 1;//標題
string title = "出 納 帳";
int strX = 0;
//フォント
Font f = new Font("MS ゴシック", 11);
int x = 50, y = 90; //印刷開始位置
int pitch = f.Height + 3; //行ピッチ
int Apage; //ページ番号
int cnt = 0; //印刷開始行
//-----表罫線-------------------------------
int topX = x;
int topY;
int[] moveX = new int[9]; //縦罫線の位置
int[] moveS = new int[9]; //文字列の位置
//セルの色(収入/支出&大科目/小科目&見出し)
//小計
HatchBrush hBrushOs = new HatchBrush(HatchStyle.LightDownwardDiagonal, Color.MistyRose, Color.White);
//1行置き
HatchBrush hBrushOg = new HatchBrush(HatchStyle.LightDownwardDiagonal, Color.Honeydew, Color.White);
//総計
HatchBrush hBrushOt = new HatchBrush(HatchStyle.LightDownwardDiagonal, Color.Lavender, Color.White);
//ヘッダー
HatchBrush hBrushOO = new HatchBrush(HatchStyle.LightDownwardDiagonal, Color.DarkSeaGreen, Color.White);
moveX[0] = x;
moveX[1] = moveX[0] + 23;
moveX[2] = moveX[1] + 23;
moveX[3] = moveX[2] + sLen[2] * 9;
moveX[4] = moveX[3] + sLen[3] * 9;
moveX[5] = moveX[4] + sLen[4] * 9;
moveX= moveX[5] + 46;
moveX[7] = moveX+ 88;
moveX= moveX[7] + 88;
int rectWidth = moveX+ 38;
int leftX = topX + rectWidth;
int rectHeight;
int botomY;
for (i = 0; i < 9; i++)
{
moveS= moveX
+ 2;
}
string[] head = new string[]
{ "月", "日", "大科目", "小科目", " 摘 要", "伝票", " 入 金", " 出 金", " 残 高" };
string[] headW = new string[] { "月", "日", "大 科 目", "小 科 目" };
int lastMoneyLineY = 0;
//------------------------------------------
//下に罫線を引くときのペン
Pen underlinePen = new Pen(Color.Black, 0.3F);
//標題
e.Graphics.DrawString(title, f, Brushes.Black, x + 50, y - 27);
//日付
f = new Font("MS 明朝", 9);
System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("ja-JP");
System.Globalization.DateTimeFormatInfo dtfi = ci.DateTimeFormat;
dtfi.Calendar = new System.Globalization.JapaneseCalendar();
System.DateTime dTime = System.DateTime.Now;
e.Graphics.DrawString(dTime.ToString("ggy年M月d日 現在", dtfi), f, Brushes.Black, leftX - 138, y - 17);
//ページ番号
f = new Font("MS ゴシック", 10);
Apage = (rowCnt % maxRow == 0) ? rowCnt / maxRow : rowCnt / maxRow + 1;
e.Graphics.DrawString(page + "/" + Apage + "page", f, Brushes.Black, leftX - 55, y - 35);//見出し
f = new Font("MS ゴシック", 11);
string hedStr;
//int strX;//セルの色
int y1 = y + f.Height - 1;
int headlineY = y1;
e.Graphics.FillRectangle(hBrushOO, topX, y1 - 20, leftX - topX, pitch - 2);
//セル小計前頁より
if (page > 1)
e.Graphics.FillRectangle(hBrushOs, topX, y1, leftX - topX, pitch);
for (i = 0; i < 9; i++)
{
switch (i)
{
case 2:
case 3:
switch (strLen)
{
case 1:
case 2:
case 3:
strX = 0;
hedStr = head;
break;
case 4:
strX = 7;
hedStr = head;
break;
case 5:
strX = 7;
hedStr = headW;
break;
default:
strX = 15;
hedStr = headW;
break;
}
e.Graphics.DrawString(hedStr, f, Brushes.Black, moveS+ strX, y);
break;
case 5:
strX = 2;
e.Graphics.DrawString(head, f, Brushes.Black, moveS
+ strX, y);
break;
default :
strX = 0;
e.Graphics.DrawString(head, f, Brushes.Black, moveS
+ strX, y);
break;
}
//e.Graphics.DrawString(hedStr , f, Brushes.Black, moveS+ strX, y);
}
//見出しの下の直線
//int y1 = y + f.Height - 1;
//int headlineY = y1;
e.Graphics.DrawLine(Pens.Black, topX, y1, leftX, y1);
y += pitch;
topY = y - pitch - 2;
lastMoneyLineY = topY;f = new Font("MS 明朝", 11);
do
{
if (rnum <= rowCnt)
{
//セルの色
y1 = y + ((cnt + 1) * pitch) - 3;
//セル1行置き
if (cnt % 2 == 0 && cnt < maxRow - 1 && rnum < rowCnt -1)
e.Graphics.FillRectangle(hBrushOg, topX, y1, leftX - topX, pitch);
//小計セル次頁へ
if (cnt == maxRow - 2)
e.Graphics.FillRectangle(hBrushOs, topX, y1, leftX - topX, pitch);
//総計セル
if (rnum == rowCnt - 2)
e.Graphics.FillRectangle(hBrushOt, topX, y1, leftX - topX, pitch);
for (i = 0; i < 9; i++)
{
e.Graphics.DrawString(hyoji[rnum, i], f, Brushes.Black, moveS, y + cnt * pitch);
}
//下に横罫線
y1 = y + ((cnt + 1) * pitch) - 3;
e.Graphics.DrawLine(underlinePen, topX, y1, leftX, y1);
lastMoneyLineY = y1;
}//行番号の更新
rnum++;
cnt++;
//改ページの確認
if (cnt >= maxRow)
{
//枠罫線
rectHeight = pitch * (maxRow + 1) - 1;
e.Graphics.DrawRectangle(Pens.Black, topX, topY, rectWidth, rectHeight);
//縦罫線
botomY = topY + rectHeight;
for (i = 0; i < 9; i++)
{
e.Graphics.DrawLine(underlinePen, moveX, topY, moveX
, lastMoneyLineY);
}
e.HasMorePages = true;
page++;
break;
}
} while (rnum != rowCnt);
//最終ページの罫線
if (rnum == rowCnt)
{
//枠罫線
rectHeight = pitch * (rnum % maxRow + 1) - 1;
e.Graphics.DrawRectangle(Pens.Black, topX, topY, rectWidth, rectHeight);
//縦罫線
botomY = topY + rectHeight;
for (i = 0; i < 9; i++)
{
e.Graphics.DrawLine(underlinePen, moveX, topY, moveX
, lastMoneyLineY);
}
}
}private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
rnum = 0;
page = 1;
}private void printPreviewDialog1_FormClosed(object sender, FormClosedEventArgs e)
{
//rnum = 0;
}private void btnMenu_Click(object sender, EventArgs e)
{
frmMain.TopMost = true;
this.Close();
frmMain.TopMost = false;
}//列幅変更のときの処理
private void suitoDataGridView_ColumnWidthChanged(object sender, DataGridViewColumnEventArgs e)
{
DataGridView dgv = (DataGridView)sender;
//ヘッダーの幅(0)+スクロールバーの幅(28)
int dgvWidth = 20;
for (int i = 1; i < 10; i++)
{
dgvWidth += dgv.Columns.Width;
}
dgv.Width = dgvWidth;
dgvToCenter();
}
//左右中央配置
private void dgvToCenter()
{
suitoDataGridView.Left = (this.ClientSize.Width - suitoDataGridView.Width) / 2;
btnPrint.Left = suitoDataGridView.Left;
btnMenu.Left = suitoDataGridView.Right - btnMenu.Width;
}private void printDocument1_EndPrint(object sender, System.Drawing.Printing.PrintEventArgs e)
{
}private void frm2SuitoPrt_Resize(object sender, EventArgs e)
{
dgvToCenter();
}private void suitoDataGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (suitoDataGridView[e.ColumnIndex, e.RowIndex].Selected)
e.CellStyle.SelectionBackColor = suitoDataGridView.CurrentCell.Style.BackColor;
}
}
}
回答
-
zen73 さんからの引用 年をとるのは悲しいもので、半年前に書いた自分のコードすらが理解できずに
困り果てています。ぜひともお助け願います。
ソースを読んで、不具合を解析しろということを求めているのでしょうか?
回答者は仕事の請負人ではありませんので、コードをぺたっと貼り付けて、「お願いします」と書かれても困ります。
ご自身で読み解き、不具合を見つけるやり方を身につけて下さい。
また、昔のコードが読めないということはよくある話ですが、この部分は何をするために書いているか等、コメントを書いておくと良いでしょう。
-----
実行結果を整理すると法則性が見えませんか?
2ページ目の前ページより 42,000 - 1ページ目の小計 10,000 = 32,000
3ページ目の前ページより 89,000 - 2ページ目の小計 57,000 = 32,000
4ページ目の前ページより 128,000 - 3ページ目の小計 96,000 = 32,000
このことから、余計な足し算が行われているのであろうことが推測できます。
32,000は本来の入金額の合計ですよね。
このあたりから、調べてみては?
なお、デバッグでブレークポイントを置いたり、ウォッチを使って変数の値を見ることは重要です。
意図した動きと異なるような数値の動きをしていたら、なぜそうなったかを追えるようにデバッグ機能を使い込んで下さい。
すべての返信
-
zen73 さんからの引用 年をとるのは悲しいもので、半年前に書いた自分のコードすらが理解できずに
困り果てています。ぜひともお助け願います。
ソースを読んで、不具合を解析しろということを求めているのでしょうか?
回答者は仕事の請負人ではありませんので、コードをぺたっと貼り付けて、「お願いします」と書かれても困ります。
ご自身で読み解き、不具合を見つけるやり方を身につけて下さい。
また、昔のコードが読めないということはよくある話ですが、この部分は何をするために書いているか等、コメントを書いておくと良いでしょう。
-----
実行結果を整理すると法則性が見えませんか?
2ページ目の前ページより 42,000 - 1ページ目の小計 10,000 = 32,000
3ページ目の前ページより 89,000 - 2ページ目の小計 57,000 = 32,000
4ページ目の前ページより 128,000 - 3ページ目の小計 96,000 = 32,000
このことから、余計な足し算が行われているのであろうことが推測できます。
32,000は本来の入金額の合計ですよね。
このあたりから、調べてみては?
なお、デバッグでブレークポイントを置いたり、ウォッチを使って変数の値を見ることは重要です。
意図した動きと異なるような数値の動きをしていたら、なぜそうなったかを追えるようにデバッグ機能を使い込んで下さい。
Azuleanさん、ありがとうございました。なんとか解決することができました。
Azulean さんからの引用 | |
|
このアドバイスを頂いて、コードを修正してみました。
bool firstPage = true; という変数を用いてページの小計計算をダブらないよう下のように修正することで解決することができました。
Azulean さんからの引用 | |
|
お叱りを受けるのは当然でした。反省しております。おかげさまで、高価なソフトを買わなくてもDataGridViewのデータを罫線付きで複数ページに印刷することができるようになりました。
private void setArray(int i) //------------------------------------------------------ if (firstPage == true) hyoji[i + idx, 7] = sum[7].ToString("#,###").PadLeft(10); rowCnt += idx + 1; do //--------------------------------------- //行番号の更新 e.HasMorePages = true;
{
if (firstPage == true)
{
hyoji[i + idx + 1, 0] = "";
hyoji[i + idx + 1, 1] = "";
hyoji[i + idx + 1, 2] = "";
hyoji[i + idx + 1, 3] = "";
hyoji[i + idx + 1, 4] = "次頁へ繰越";
//------------------------------------------------------
hyoji[i + idx + 2, 7] = sum[7].ToString("#,###").PadLeft(10);
hyoji[i + idx + 2, 8] = (sum[6] - sum[7]).ToString("#,###").PadLeft(10);
}
}
{
hyoji[i + idx, 0] = "";
hyoji[i + idx, 1] = "";
//-----------------------------------------------------
hyoji[i + idx, 8] = (sum[6] - sum[7]).ToString("#,###").PadLeft(10);
}
{
if (rnum <= rowCnt)
{
}
rnum++;
cnt++;
//改ページの確認
if (cnt >= maxRow)
{
firstPage = false;
page++;
break;
}
} while (rnum != rowCnt);