C#のExcel操作備忘録

Excel.Worksheet sheet = null;
Excel.Range range = null;

 

 

縦書きにしたセルを印刷の時に切れちゃうので大きくする

range = sheet.get_Range("A5");
range.RowHeight = range.Height + 30;
range = null;

 

 

印刷可能サイズの取得(A4の場合)

double printable_height;
double printable_width;
double paper_height;
double paper_width;

if (sheet.PageSetup.Orientation == Excel.XlPageOrientation.xlPortrait)
{
//縦 297mm 1mm = 2.83pt;
paper_height = 297 * 2.83;
paper_width = 210 * 2.83;
}
else
{
//横 210mm 1mm = 2.83pt;
paper_height = 210 * 2.83;
paper_width = 297 * 2.83;
}



double BottomMargin = sheet.PageSetup.BottomMargin;//pt
double TopMargin = sheet.PageSetup.TopMargin;//pt
printable_height = paper_height - BottomMargin - TopMargin;

double RightMargin = sheet.PageSetup.RightMargin;//pt
double LeftMargin = sheet.PageSetup.LeftMargin;//pt
printable_width = paper_width - RightMargin - LeftMargin;



System.Diagnostics.Debug.Print("印刷可能高さ:" + printable_height.ToString() + "pt");
System.Diagnostics.Debug.Print("印刷可能幅:" + printable_width.ToString() + "pt");

 

 

ページ縮小率のチェック(横1ページ・縦自動の場合)

「印刷可能サイズの取得」から続きます
last_colnameに一番右のセル列を設定しておきます(ループで探してもよいが、時間がかかるのでどこかの処理で取得しておく)
例:last_colname = “AA”;

range = sheet.get_Range("A1", last_colname + "1");
last_col_x = range.Width;
range = null;
if (printable_width < last_col_x)
{
printable_height = printable_height * (last_col_x / printable_width);
}

 

グラフや図を切れないように改ページさせる

セルの高さをグラフや図の大きさに変えてやれば縦で切られない。
同様に横で切られる場合にはセルの横サイズを大きくすればいい。

ただし、結合セルは不可。
単一セルにしたときのみ改ページで切られない。

↑こんなイメージ↓

chart_row = 10;//入れ込む行
chartwidth = 300;
chartheight = 200;
top_margin = 10;
bottom_margin = 10;

location_x = 10;
location_y = sheet.get_Range("A" + chart_row).Top + top_margin;

range = sheet.get_Range("A1");
range.RowHeight = chartheight + top_margin + bottom_margin;

chart = sheet.ChartObjects().Add(location_x, location_y, chartwidth, chartheight);

 

散布図関連

一気にまとめるとこんな感じです。
最後のソースに問題点3つまとめています。

散布図グラフに使えるX軸、Y軸の設定

単純にrangeで”A1:B2″とかだとX軸Y軸の設定ができないので以降を参照してください。
XValuesとValuesを使用します。

 

散布図グラフの点の縁取り(枠線)を消す

マーカーをよく見ると縁取りになっているので同職を使って消します。
線を軟化いじるとマーカーからマーカーの間に線が入るので、
そうではない設定でツボりました。

◆ー◆の線ではなく◆の縁取り◇を同じ色にして消したかった。

 

X軸、Y軸のラベルを変える

既出ですがついでにです

 

まとめるとこんな感じ↓

//値A×値B
chart_row = 10;//10行目に書く
chart_margin_vertical = 10;//グラフの上下マージン
location_x = sheet.Range["A"+ chart_row].Width / 2;
location_y = sheet.get_Range("A" + chart_row, "A" + chart_row).Top + chart_margin_vertical / 2;
chartwidth = 300;
chart = sheet.ChartObjects().Add(location_x, location_y, chartwidth, chartHeight);
chartpage = chart.Chart;
chartrange = sheet.get_Range("A1:A2");//これはダミーレンジ

chart.Placement = Excel.XlPlacement.xlFreeFloating;//グラフのサイズをセル幅に合わせて変更しない&場所を動かさない


//グラフの作成
chartpage.SetSourceData(chartrange);
chartpage.HasLegend = false;        //凡例
chartpage.HasTitle = true;          //タイトル
chartpage.PlotArea.Format.Fill.ForeColor.RGB = Color.LightGray.ToArgb();//背景色
chartpage.PlotArea.Format.Line.ForeColor.RGB = Color.Black.ToArgb();//文字色
chartpage.ChartType = Excel.XlChartType.xlXYScatter;
chartpage.ChartTitle.Format.TextFrame2.TextRange.Font.Size = standardFontSize;
chartpage.ChartTitle.Text = "値A×値B";
chartpage.ChartGroups(1).GapWidth = 200;

//データの場所は値Aが"A100:A200"、値Bが"B100:B200"とする
start_row = 100;
end_row = 200;

tmp_objSeries = chartpage.SeriesCollection(1);
tmp_objSeries.XValues = sheet.get_Range("A" + start_row + ":" + "A" + end_row);
tmp_objSeries.Values = sheet.get_Range("B"+ start_row  + ":" + "B"+ end_row);
tmp_objSeries.MarkerBackgroundColor = ColorTranslator.ToWin32(Color.Blue);//マーカーの中
tmp_objSeries.MarkerForegroundColor = ColorTranslator.ToWin32(Color.Blue);//マーカーの外線
tmp_objSeries.MarkerSize = markersize;

valueAxis = chartpage.Axes(Excel.XlAxisType.xlCategory, Excel.XlAxisGroup.xlPrimary);
valueAxis.HasTitle = true;
valueAxis.AxisTitle.Text = "値A";
valueAxis.TickLabels.NumberFormatLocal = "#0";

valueAxis = chartpage.Axes(Excel.XlAxisType.xlValue, Excel.XlAxisGroup.xlPrimary);
valueAxis.HasTitle = true;
valueAxis.AxisTitle.Text = "値B";
valueAxis.TickLabels.NumberFormatLocal = "#0";

 

短納期で必死だったから何をやったかも、うろ覚えだけど

備忘録として…です。

 

C# Excelに改ページをを入れて「HRESULT からの例外です : 0x800A03EC」

既出のとおりC#やVBやVBAでExcelファイルを作って
改ページを入れるときは

xlRange = xlSheet.get_Range("A10", "A10");
xlSheet.HPageBreaks.Add(xlRange);

こんな感じに書きます。
上の例は水平に買いぺページを入れる例です。

 

表題の通り

「HRESULT からの例外です : 0x800A03EC」

が出てしまってツボッた原因は

レンジが”A1:A1″はエラーになります!!!!

水平の改ページ設定はA2以降で!

同じようにたぶん垂直の改ページ設定はB1からだと思います

うううう…ツボった…(;~;)

 

キリのいい上限値を出す計算式(キリ番計算式)

グラフを書くときの上限値を出すときに例えば最大値が52.6とかだったら53というようなキリのいい数字で締めたらキレイですよね。

そういうときのキリの良い数字を求める計算方法です

C#でチャートコントロールを使うなら
こんな感じで設定

//Y軸最小値、最大値、目盛間隔の設定
chart1.ChartAreas[0].AxisX.Maximum = MAXVALUE_X ;
chart1.ChartAreas[0].AxisY.Maximum = MAXVALUE _Y;

上位2桁でキリの良い上限値を求める方法

【例】

  • 52.6753→53.0000
  • 0.124→0.200
  • 15473→16000

C#で上2桁のキリ番を計算

double dblVal_In = 52.6753;//←暫定的な最大値

strVal = dblVal_In.ToString(“0.0E+0”);
intPos = strVal.IndexOf(“E”) + 1;
dblVal_new = double.Parse(strVal);
if (dblVal_new < dblVal_In)
{
dblVal_new = dblVal_new + Convert.ToDouble(“0.1” + *注Mid(strVal, intPos));
}

double MAXVALUE = dblVal_new;//←キリの良い数字

 

 

 

VB6(VBA)で上位2桁のキリ番を計算

strVal = 52.6753′暫定的な最大値

strVal = Format$(dblVal_In, “0.0E+##”)
intPos = InStr(1, strVal, “E”)
dblVal_new = CDbl(strVal)
If dblVal_new < dblVal_In Then
dblVal_new = dblVal_new + CDbl(“0.1” & mID$(strVal, intPos))
End If

MAXVALUE = dblVal_new;//←キリの良い数字

 

 

上位1桁でキリの良い上限値を求める方法

【例】

  • 52.6753→60.0000
  • 0.124→1.000
  • 15473→20000

C#で上1桁のキリ番を計算

double dblVal_In = 52.6753;//←暫定的な最大値

strVal = dblVal_In.ToString(“0.E+0”);
intPos = strVal.IndexOf(“E”)+1;
dblVal_new = double.Parse(strVal);
if (dblVal_new < dblVal_In)
{
dblVal_new = dblVal_new + Convert.ToDouble(“1” + *注Mid(strVal, intPos));
}
double MAXVALUE = dblVal_new;//←キリの良い数字

 

VB6(VBA)で上位1桁のキリ番を計算

strVal = 52.6753′暫定的な最大値

strVal = Format$(dblVal_In, “0.E+##”)
intPos = InStr(1, strVal, “E”)
dblVal_new = CDbl(strVal)
If dblVal_new < dblVal_In Then
dblVal_new = dblVal_new + CDbl(“1” & mID$(strVal, intPos))
End If

MAXVALUE = dblVal_new;//←キリの良い数字

 

キリ番計算の考察

※注
C#の方では。ここでMidという関数を作って使っています。
詳細はコチラのサイトを参考にしてください→「VB の Left, Mid, Right のように文字列を取り出す


ここで使っている計算はイロイロな上限値でキリ番にできるようになっていますので、関数かしておくと便利です。
私が使ったときはイロイロな種類のグラフを書くので上限値が250だったり9.84だったりのキリ番を求めなきゃいけないときに使いました。

多分あっていると思う…

こういうのって納品した後に備忘録として書くからガッツリとデバッグしてないんだよね…(=_=;)
まちがってたらごめん。でもこんな感じで考えりとできますってことで参考に。

 

 

Chartコントロールでラベルやグラフの設定

VisualStudioのChartコントロール

あまり有名ではないけど、とても便利で簡単なのでC#での使い方を備忘録。
とりあえず自分がやったグラフだけ書きますが
細かい設定まで書いているので参考にしてください。

コントロールの貼り付け

「ツールボックス」「データ」の中にあるチャートをドラッグドロップ

 

チャートの初期化

//初期化
chart1.Series.Clear();

//X軸最小値、最大値、目盛間隔の設定
chart1.ChartAreas[0].AxisX.Minimum = 0;
chart1.ChartAreas[0].AxisX.Maximum = 20;
chart1.ChartAreas[0].AxisX.Interval = 5;

//Y軸最小値、最大値、目盛間隔の設定
chart1.ChartAreas[0].AxisY.Minimum = 0;
chart1.ChartAreas[0].AxisY.Maximum = 50;
chart1.ChartAreas[0].AxisY.Interval = 10;

//背景色
chart1.ChartAreas[0].BackColor = Color.FromArgb(255,200,200,200);

//中の罫線を点線にと色
chart1.ChartAreas[0].AxisX.MajorGrid.LineColor = Color.HotPink;
chart1.ChartAreas[0].AxisX.MajorGrid.LineDashStyle = ChartDashStyle.Dot;
chart1.ChartAreas[0].AxisY.MajorGrid.LineColor = Color.Brown;
chart1.ChartAreas[0].AxisY.MajorGrid.LineDashStyle = ChartDashStyle.Dot;

折れ線グラフの書き方

例:「全国」という名前の青くてちょっと太い線のy=5x+10なグラフ

Series series_all = new Series(“全国”);
{
for (int i = 0; i < 50; i++)
{
int x = i;
int y = (5 * x) + 10;

series_all.Points.AddXY(x, y);
}
series_all.ChartType = SeriesChartType.Line;//グラフの種類
series_all.Color = Color.Blue;//線の色
series_all.BorderWidth = 3;//線の幅
series_all.IsValueShownAsLabel = false;//ポイントごとの値を表示しない
}
chart1.Series.Add(series_all);

 

 

 

分布図の書き方

なんのグラフなんだか…(-_-;)

string[] ary_tdfk = { “北海道”, “青森”, “岩手”, “秋田”, “山形”, “福島” };
double[] ary_y ={ 20.5, 10, 12.8, 7, 25.2, 9 };
long[] ary_x={ 15, 8, 4, 10, 7, 5};

//分布図
Series series_spraying = new Series(“散布図”);
{
//描画形式の設定
series_spraying.MarkerSize = 10;//点の大きさ
series_spraying.MarkerStyle = System.Windows.Forms.DataVisualization.Charting.MarkerStyle.Diamond; //点の形
series_spraying.ChartType = SeriesChartType.Point;//グラフのスタイル
series_spraying.Font = new Font(“Arial”, 8);//文字フォントとサイズ
series_spraying.Name = “散布図”;

//描画
for (int i = 0; i < ary_tdfk.Length; i++)
{
DataPoint dp = new DataPoint(ary_x[i], ary_y[i]);
dp.Label = ary_tdfk[i];
series_spraying.Points.Add(dp);
}
}
chart1.Series.Add(series_spraying);

ラベルのカスタマイズ

chart1.Series[“散布図”].LabelBackColor = Color.LightYellow;//ラベルの背景色
chart1.Series[“散布図”].CustomProperties = “LabelStyle=BottomRight”;//ラベルの位置
chart1.Series[“散布図”].Color = Color.Aqua;//ポイントの色

 

 

ラベルが重なってもいい、または重ねない

上のラベルはラベルを重ねない状態です。

密集した場所だと→とか自動で出るので結構便利ですが逆に分かりにくい場合は重なってもいいからという場合は

chart1.Series[“散布図”].SmartLabelStyle.Enabled = false;//ラベルの自動移動

 

凡例の削除

ちょっと場所を取りすぎるので邪魔ですよね

//凡例の非表示
for (int i = 0; i < chart1.Series.Count; i++)
{
chart1.Series[i].IsVisibleInLegend = false;
chart1.Series[i].IsValueShownAsLabel = false;
}

 

チャートをクリックしたときに値を表示

private void chart1_Click(object sender, EventArgs e)
{
HitTestResult result;
result = this.chart1.HitTest(((MouseEventArgs)e).X, ((MouseEventArgs)e).Y);
if (result.ChartElementType == ChartElementType.DataPoint)
{
DataPoint dp = result.Series.Points[result.PointIndex];
label1.Text = “エリア:” + dp.Label + “ X=” + dp.XValue.ToString() + “ Y=” + dp.YValues[0].ToString();
}

}

  ↓

「山形」の点をクリックすると「label1」に内容を書き出します

  ↓

 

複数グラフがあるときに特定のグラフの時だけ値を表示

上のままだと直線をクリックしたときに値が出てしまいます。
これを都道府県名の時だけ表示にします。

 

private void chart1_Click(object sender, EventArgs e)
{
label1.Text = “”;

HitTestResult result;
result = this.chart1.HitTest(((MouseEventArgs)e).X, ((MouseEventArgs)e).Y);
if (result.ChartElementType == ChartElementType.DataPoint)
{
if (result.Series.Name == “散布図”)
{
DataPoint dp = result.Series.Points[result.PointIndex];
label1.Text = “エリア:” + dp.Label + “ X=” + dp.XValue.ToString() + “ Y=” + dp.YValues[0].ToString();
}
else
{
label1.Text = “”;
}
}
}

 

chartコントロールを使わない場合

Chartコントロールを使わない場合はPictureboxもしくはFormに書きます。

下に進むとY軸は+され、右に進むとX軸が+されるので
グラフの(0,0)の位置を決定してから
計算して出た値のポイントまでラインを書いていきます。

 

 

Chartコントロールの感想

昔はねぇ…こういう便利なのがなかったから大変でした。
いろいろなグラフをきれいにかけるので是非とも活用してほしいと思います。

特にこのグラフのすごい点はchartのアンカーを4方位に設定して
ウィンドウを拡縮したときに同じようにchartコントロームが拡縮したときに
スムーズに描画がされる点です。