2010年06月28日


PHP : TCPDF で業務系コントロールブレイク連続帳表印字サンプル

グループヘッダーとグループ合計があり、ブレイクでの改ページはありませんが、印字できる行数に対して、ヘッダーと合計行のコントロールがあります。特に、合計行を印字しようとした時に行が無い場合、改ページした後にタイトルを印字し、ブレイク前のヘッダを印字する必要があります。

PDF出力サンプル(2ページ目先頭)

所属別支給額合計表


関連する記事

VBScript : TCPDFで MSフォントが使えるようにする全自動スクリプト
PHP : TCPDF の Cell を使って位置指定印字を行うサンプル
PHP : TCPDF の Cell で一覧表を印字するサンプル
VB.net : 印刷サンプルスケルトン
※ 以下のソースコードは utf8n で保存して下さい
<?php
//***************************************
// require の 検索パスを設定
//***************************************
$path = "C:\\user\\web\\tcpdf_5_5_001";
set_include_path(get_include_path() . PATH_SEPARATOR . $path);

//***************************************
// TCPDF ライブラリ
//***************************************
require_once('tcpdf/config/lang/eng.php');
require_once('tcpdf/tcpdf.php');

//***************************************
// Windows の場合は MySQL用の外部ライブリをロード
//***************************************
if ( substr(PHP_OS,0,3) == 'WIN' ) {
	if ( !extension_loaded( "mysql" ) ) {
		dl("php_mysql.dll");
	}
}

//***************************************
// MySQL 接続文字列
//***************************************
$Server = 'localhost';
$DbName = 'lightbox';
$User = 'root';
$Password = 'password';

//***************************************
// 接続
//***************************************
$Connect = @mysql_connect( $Server, $User, $Password );
if ( !$Connect ) {
	header( "Content-Type: text/html; Charset=euc-jp" ); 

	mb_language( "ja" );
	mb_internal_encoding("UTF-8");
	$str = mb_convert_encoding( "接続エラーです", "euc-jp", "utf-8" );
	print $str;

	exit();
}

//***************************************
// 必要なら、DB からのキャラクタセットを変換する
// ( PHP 5 >= 5.2.3 ) で利用可能
// ※ DB が utf8でソースもutf8 なら必要ありません
// ※ php5.2.3 より前なら mb_convert_encoding で日本語を
//   変換します
//***************************************
// mysql_set_charset("utf8", $Connect);
//mysql_set_charset("eucjpms", $Connect);
//mysql_set_charset("cp932", $Connect);

//***************************************
// DB選択
//***************************************
mysql_select_db( $DbName, $Connect );

//***************************************
// クエリ
//***************************************
$query = "select 社員マスタ.*,コード名称マスタ.*,DATE_FORMAT(生年月日,'%Y-%m-%d') as 誕生日";
$query .= " from 社員マスタ left outer join コード名称マスタ";
$query .= " on 社員マスタ.所属 = コード名称マスタ.コード ";
$query .= " where コード名称マスタ.区分 = 2";
$query .= " order by 所属";
$result = mysql_query($query, $Connect);

//***************************************
// PDFオブジェクトを作成
//
// TCPDF __construct(
// [string $orientation = 'P'],
//   P or PORTRAIT(縦:既定)
//   L or LANDSCAPE(横))
// [string $unit = 'mm'],
//   pt: ポイント
//   mm: mm(既定)
//   cm: cm
//   in: インチ
// [mixed $format = 'A4'],
//    4A0 | 2A0 | A0 | A1 | A2 | A3 | A4(既定) | A5 | A6 | A7 | A8 | A9 | A10
//   | B0 | B1 | B2 | B3 | B4 | B5 | B6 | B7 | B8 | B9 | B10
//   | C0 | C1 | C2 | C3 | C4 | C5 | C6 | C7 | C8 | C9 | C10
//   | RA0 | RA2 | RA3 | RA4 | SRA0 | SRA1 | SRA2 | SRA3 | SRA4
//   | LETTER | LEGAL | EXECUTIVE | FOLIO 
// [boolean $unicode = true],
// [String $encoding = 'UTF-8'],
// [boolean $diskcache = false]) 
//

//***************************************
$pdf = new TCPDF(
	PDF_PAGE_ORIENTATION,
	PDF_UNIT,
	PDF_PAGE_FORMAT,
	true,
	"UTF-8",
	false
); 
//***************************************
// ヘッダーとフッターは無し
//***************************************
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);

//***************************************
// ページコントロール用変数
// 
// $line_no は次に印字する行
// ※ この場合タイトル行数も含む
//***************************************
$line_no = 0;
$line_max = 16;
$data_top = 25;
$data_left = 10;
$page_no = 1;
$break_syozoku = false;
$break_code = "";
$save_data = array();
$ksum = 0;

//***************************************
// 1ページ目(ページの追加)
//***************************************
$pdf->AddPage();

//***************************************
// 日本語データを扱うので、使うフォントを
// 日本語フォントに設定する
//***************************************
$pdf->SetFont('msmincho', '', 8);

//***************************************
// データの出力
//***************************************
while ($row = mysql_fetch_array($result, MYSQL_BOTH)) {

	// 所属ブレイク状態の設定
	if ( $break_code != $row['所属'] ) {
		$break_syozoku = true;
	}

	//合計印字 : 初回以外のブレイク発生時
	if ( $break_syozoku && $break_code != '') {
		user_break_sum($pdf);
	}

	// ここでは既にデータが存在する事が確定しているので、
	// 初回および最大印字行数をオーバーしている場合はヘッダを印字する
	if ( $line_no == 0 || $line_no > $line_max ) {
		user_titie( $pdf );
	}

	// ページの最初と、ブレイク発生時
	if ( $line_no == 3 || $break_syozoku ) {
		user_break_header( $pdf );
	}


	// 社員名出力
	// $data_top : 開始 Y マージン
	// タイトルからの距離 + 5
	// 行間 * 5
	$row_position = $data_top + 5 +($line_no-3) * 5;
	text( $pdf,  $data_left + 0,  $row_position, $row['社員コード'] );
	text( $pdf,  $data_left + 15, $row_position, $row['氏名'] );
	// 右寄せ出力は幅を指定する
	textR( $pdf, $data_left + 35, $row_position, user_number_format($row['給与']), 20 );

	// 集計処理
	$ksum += $row['給与'];

	// 次の印字行
	$line_no++;

	// 処理の最終に前回データを保存する
	$break_code = $row['所属'];
	$save_data = $row;
	$break_syozoku = false;

}

// 最終ブレイク
user_break_sum($pdf);


//***************************************
//PDFを出力
// Output(
// [string $name = 'doc.pdf'],
// [string $dest = 'I'])
// I: ブラウザに出力する(既定)、
// D: ブラウザで(強制的に)ダウンロードする。
// F: ローカルファイルとして保存する。
// S: PDFドキュメントの内容を文字列として出力する。
//***************************************
$pdf->Output("sample.pdf", "I");

//***************************************
// MySQL 接続解除
//***************************************
mysql_close($Connect);


//***************************************
// タイトル部印字関数
//***************************************
function user_titie( $pdf ) {

	global $line_no;
	global $data_top,$data_left;
	global $page_no;

	// 初回以外は改ページ
	if ( $line_no != 0 ) {
		$pdf->AddPage();
	}

	// 帳表タイトル
	$pdf->SetFont('msmincho', '', 20);
	text( $pdf,  $data_left + 30, 8, "** 所属別支給額合計表 **"  );

	// 明細タイトル
	$pdf->SetFont('msmincho', '', 8);
	text( $pdf,  $data_left + 0,  $data_top + 0, "社員CD"  );
	text( $pdf,  $data_left + 15, $data_top + 0, "氏名"  );
	textR( $pdf, $data_left + 35, $data_top + 0, "給与", 20  );

	// ページ
	text( $pdf,  $data_left + 140, 8, "page " );
	textR( $pdf, $data_left + 145, 8, user_number_format($page_no), 10 );

	// 画像出力
	// ファイル名は、http://〜 を指定可能
/*
	$pdf->Image(
		'./winofsql.png',
		$data_left + 0,
		9,
		0,
		0,
		'PNG',
		'http://winofsql.jp/',
		'',
		false,
		300,
		'',
		false,
		false,
		0,
		false,
		false,
		false
	); 
*/

	$line_no = 3;
	$page_no++;

}

//***************************************
// 所属ブレイクヘッダ
//***************************************
function user_break_header($pdf,$opt=0) {

	global $line_max;
	global $line_no;
	global $row,$save_data;
	global $data_left,$data_top;

	// 最終行にブレイクヘッダのみ印字しない
	// ( よって、次に印字する行が最終行の場合は改ページ )
	if ( $line_no > $line_max - 1 ) {
		user_titie( $pdf );
	}

	$row_position = $data_top + 5 +($line_no-3) * 5;
	text( $pdf,  $data_left + 0, $row_position, "所属" );
	if ( $opt == 0 ) {
		text( $pdf,  $data_left + 10, $row_position, $row['名称'] );
	}
	else {
		text( $pdf,  $data_left + 10, $row_position, $save_data['名称'] );
	}

	// 次の印字行
	$line_no++;
}

//***************************************
// 所属ブレイク合計
//***************************************
function user_break_sum($pdf) {

	global $line_max;
	global $line_no;
	global $row;
	global $data_left,$data_top;
	global $ksum;

	// 改ページ条件では、ブレイクヘッダが必要
	if ( $line_no > $line_max ) {
		user_titie( $pdf );
		user_break_header($pdf,1);
	}

	$row_position = $data_top + 5 +($line_no-3) * 5;
	text( $pdf,  $data_left + 15, $row_position, "合計" );
	// 右寄せ出力は幅を指定する
	textR( $pdf, $data_left + 35, $row_position, user_number_format($ksum), 20 );

	// 集計データを使用したので、初期化
	$ksum = 0;

	// 次の印字行
	$line_no++;
}

//***************************************
// カンマ編集( 空文字は 0 )
//***************************************
function user_number_format($param) {

	if ( trim($param) == '' ) {
		$param = "0";
	}

	return number_format($param);

}

//***************************************
// 位置指定印字( 左詰め )
//***************************************
function text( $pdf, $x=0, $y=0, $txt='', $w=1, $h=0  ) {

	$a = $pdf->GetX();
	$b = $pdf->GetY();

	$pdf->SetXY( $x, $y );
	$pdf->Cell($w, $h, $txt, 0, 0, 'L');

	$pdf->SetXY($a,$b);

}

//***************************************
// 位置指定印字( 右詰め )
//***************************************
function textR( $pdf, $x=0, $y=0, $txt='', $w=1, $h=0  ) {

	$a = $pdf->GetX();
	$b = $pdf->GetY();

	$pdf->SetXY( $x, $y );
	$pdf->Cell($w, $h, $txt, 0, 0, 'R');

	$pdf->SetXY($a,$b);

}

?>





タグ:TCPDF PHP 印刷
posted by at 2010-06-28 15:52 | PHP | このブログの読者になる | 更新情報をチェックする

2010年01月21日


PHP+MySQL+GD+フォントでアクセスカウンタ



<img
	src="page_counter.php?id=myPage"
	style='
		border-style:solid;
		border-color:#000000;
		border-width:1px;
	' 
/>
上記のように、myPage を指定するだけで、自動的に行が作成されて加算されていきます。もしテーブルが無い場合は最初に一度だけテーブル作成が行われます ※ trust.lst に無い URL で、使用する事ができないようになっています
■ 著作権その他

このプログラムはフリーです。どうぞ自由に御使用ください。
著作権は作者である私( lightbox )が保有しています。
また、本ソフトを運用した結果については、作者は一切責任を
負えせんのでご了承ください。

lightbox
同梱している 7barPBd.TTF は以下のサイトよりダウンロードして使用しています単位変換/デジタル時計フォン/Illustratorソフト/定規
<?php
header("Content-type: image/png");
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "pragma: no-cache" );
header( "Cache-control: no-cache" );

# ***************************
# DB 情報
# ***************************
$server = 'localhost';
$dbname = 'lightbox';
$user = 'root';
$password = 'password';

# **************************************
# 埋め込みを許可したページ以外はエラー
# **************************************
$trust = false;
$file = file( "trust.lst" );	// 許可対象 URL の先頭文字列リスト
for( $i = 0; $i < count( $file ); $i++ ) {

	# 改行削除
	$target = rtrim( $file[$i] );

	# 空行は無視
	if ( $target == "" ) {
		continue;
	}

	# コメント文字
	if ( substr( $target, 0, 1 ) == ";" ) {
		continue;
	}

	$len = strlen( $target );
	$ref = substr( $_SERVER['HTTP_REFERER'], 0, $len );
	if ( $target == $ref ) {
		$trust = true;
		break;
	}
}

# ***************************
# 使用不可
# ***************************
if ( !$trust ) {
	// 使用権限なし
	$img_text = "8888888888";
}
else {
	# ***************************
	# id が指定されていない場合
	# ***************************
	if ( $_GET['id'] == '' ) {
		$_GET['id'] = "default";
	}

	// 接続
	$connect = @mysql_connect( $server, $user, $password );
	# ***************************
	# 処理
	# ***************************
	if ( $connect ) {
		mysql_select_db( $dbname, $connect );
		$_GET['id'] = mysql_real_escape_string( $_GET['id'], $connect );


# ***************************
# SQL文ヒアドキュメント
# ***************************
$query_update = <<<QUERY_UPDATE
update page_counter
	set access_count = access_count + 1
	where page_id = '{$_GET['id']}'
QUERY_UPDATE;

$query_insert = <<<QUERY_INSERT
insert into page_counter
	values('{$_GET['id']}',0)
QUERY_INSERT;

$query_create = <<<QUERY_CREATE
create table page_counter (
	page_id VARCHAR(20)
	,access_count INT
	,primary key(page_id)
)
QUERY_CREATE;

$query_select = <<<QUERY_SELECT
select * from page_counter
	where page_id = '{$_GET['id']}'
QUERY_SELECT;

		// 更新処理( +1 )
		$result = mysql_query($query_update,$connect);
		if ( !$result ) {
			$result = mysql_query($query_create,$connect);
			// 新規行追加
			$result = mysql_query($query_insert,$connect);
			$result = mysql_query($query_update,$connect);
		}
		else {
			if ( mysql_affected_rows($connect) == 0 ) {
				$result = mysql_query($query_insert,$connect);
				$result = mysql_query($query_update,$connect);
			}
		}
		// 更新結果読み出し
		$result = mysql_query($query_select,$connect);
		$column = mysql_fetch_row($result);
	
		$img_text = sprintf( "%010d", $column[1]+0 );
	}
	else {
		// 接続エラー
		$img_text = "0000000000";
	}
}

$font_path = "./7barPBd.TTF";

# ***************************
# キャンバス作成
# ***************************
$im = imagecreate( 150, 30 );

# ***************************
# 画像の背景色
# imagecolorallocate() の最初のコールで背景色がセットされます
# ***************************
$white = imagecolorallocate( $im, 255, 255, 255 );

# ***************************
# 画像の文字色
# ***************************
$black = imagecolorallocate( $im, 0, 0, 0 );

imagettftext(
	$im,
	20,	# サイズ
	0,	# 角度
	5,	# x 座標
	25,	# y 座標
	$black,
	$font_path,
	$img_text);

# ***************************
# PNG 出力
# ***************************
imagepng($im);

# ***************************
# 終了処理
# ***************************
imagecolordeallocate( $im, $black );
imagecolordeallocate( $im, $white );
imagedestroy($im);

?>




タグ:PHP gd MySQL font
posted by at 2010-01-21 20:27 | PHP | このブログの読者になる | 更新情報をチェックする

2009年07月13日


アップロードされたファイルを縮小して保存

$_FILES に格納されているアップロードが成功した一時ファイルの名前より、それを加工して実際のアップロードディレクトリに格納しています

( ※ 必要ならば、回転も行います )
// *****************************************
// アップロードされたファイルを縮小して保存
// *****************************************
function ImageConvert() {

	global $image_dir,$err_message;

	$err_message = "";

	$upload = $image_dir ."/";
	$_POST['prefix'] = trim($_POST['prefix']);
	if ( $_POST['prefix'] != '' ) {
		$upload .= $_POST['prefix'] ."-";
	}
	$upload .= $_FILES['MyUploadFile']['name'];
 
	# テンポラリディレクトリにある実際のファイル
	$file	= $_FILES['MyUploadFile']['tmp_name'];
 
	# ファイルの属性等を取得
	$target	= getimagesize( $file );
 
	# 現在のサイズ
	if ( $_POST['role'] == '1' ) {
		$width	= $target[1];
		$height	= $target[0];
	}
	else {
		$width	= $target[0];
		$height	= $target[1];
	}

	# 横
	if ( $width > $height ) {
		if ( $width <= 500 ) {
			move_uploaded_file(
				$_FILES['MyUploadFile']['tmp_name'], $upload );
			return;
		}
		$width_new	= 500;
	}
	# 縦
	else {
		if ( $width <= 400 ) {
			move_uploaded_file(
				$_FILES['MyUploadFile']['tmp_name'], $upload );
			return;
		}
		$width_new	= 400;
	}
 
	$height_new = (int)( ($height/$width)*$width_new );
 
	# JPEG

	# 元のファイルのハンドル
	$jpeg		= imagecreatefromjpeg ( $file );
	if ( $_POST['role'] == '1' ) {
		$jpeg = imagerotate($jpeg, -90, 0);
	}
	if ( $_POST['role'] == '2' ) {
		$jpeg = imagerotate($jpeg, 90, 0);
	}
	# 新しいイメージ
	$jpeg_new = imagecreatetruecolor( $width_new, $height_new );
	# サイズ変更して新しいイメージへ転送
	$ret = imagecopyresampled(
		$jpeg_new,
		$jpeg,
		0,
		0,
		0,
		0,
		$width_new,
		$height_new,
		$width,
		$height
	);

	if ( !$ret ) {
		$err_message = "サイズ変更に失敗しました";
		return;
	}

	# JPEG ファイルとして、クオリティ 75 で出力
	$ret = imagejpeg ( $jpeg_new, $upload, 75);
	if ( !$ret ) {
		$err_message = "ファイル作成に失敗しました";
		return;
	}

}





posted by at 2009-07-13 15:16 | PHP | このブログの読者になる | 更新情報をチェックする

2009年07月12日


PHP の Split は explode

通常日本語を扱う場合、カンマ等日本語に含まれ無い区切り文字を使う場合、この関数で OK ですが、問題の出る可能性のある区切り文字の場合は、mb_split を使うと良いでしょう。
<?
$str = "A,B,C";

$aData = explode(",",$str);

$result = "";

for( $i = 0; $i < count($aData); $i++ ) {
	If ( $result != "" ) {
		$result = $result . ",";
	}
	$result = $result . $aData[$i];
}

print $result;

?>



タグ:String
posted by at 2009-07-12 20:56 | PHP | このブログの読者になる | 更新情報をチェックする

2009年06月12日


PHP5で使うクラスの基本的な機能をまとめたサンプル


<?php
class r205 {

	// オブジェクト定数
	const label = 'R205 Object';
	// クラス変数
	public static $ver = "090612";
	// インスタンス変数
	public $r205_charset;

	// PHP4 から一般的なクラス名と同名のコンストラクタ
	function r205( $charset ) {

		// インスタンス変数の設定
		$this->r205_charset = $charset;

	}

	// static メソッド
	static function phpuser() {
		print "<PRE>";
		
		print "PHP version : " . phpversion() . "\n";
		print "include_path : " . get_include_path() . "\n";
		print "get_magic_quotes : " . get_magic_quotes_gpc . "\n";
		print "variables_order : " . ini_get('variables_order') . "\n";
		print "short_open_tag : " . ini_get('short_open_tag') . "\n";
		print "display_errors : " . ini_get('display_errors') . "\n";
		print "display_startup_errors : " . ini_get('display_startup_errors') . "\n";
		print "allow_url_fopen : " . ini_get('allow_url_fopen') . "\n";
		print "allow_url_include : " . ini_get('allow_url_include') . "\n";
		print "max_execution_time : " . ini_get('max_execution_time') . "\n";
		print "post_max_size : " . ini_get('post_max_size') . "\n";
		print "track_errors : " . ini_get('track_errors') . "\n";
		print "</PRE>";
	}

	// メソッド
	function httpHeader( ) {
		// インスタンス変数の参照
		header( "Content-Type: text/html; Charset={$this->r205_charset}" );
		header( "pragma: no-cache" );
		header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
		header( "Cache-control: no-cache" );
	}

	// メソッド
	function debugPrint( $target ) {

		print "<PRE>";
		print_r( $target );
		// クラス変数の参照( 埋め込み不能 )
		print "\nversion:".self::$ver."\n";
		print "</PRE>";

	}


	// オブジェクトを print しようとした時等に使用される
	function __toString() {
		// オブジェクト定数の参照
		return self::label;
	}
}

$a = new r205("SHIFT_JIS");
// 共通 http ヘッダの出力
$a->httpHeader();

// __toString を実行させる
print "$a<br>";
// クラス変数を変更
r205::$ver = "091231";
// static メソッドを実行
r205::phpuser();
// インスタンスメソッドを実行
$a->debugPrint($_SERVER);


?>





タグ:class PHP クラス
posted by at 2009-06-12 11:29 | PHP | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します