4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PDF(SBI証券 株式等配当金のお知らせ)からCSV(テキスト)を作成する

Last updated at Posted at 2020-09-16

2022-09-07 使い方の改善。setwd()、getwd()
2020-11-23 Rパッケージ化

やりたい事

法人税の決算作業で「受取配当金を集計する」のですが、

SBI証券の場合、元ネタがPDF形式なのですよ。
↓サンプル
2020-09-13 9.24のイメージ.jpeg

昔はこのPDFを見て転記(手入力)してた。
数枚(2〜3枚)だから、しょうがないな、と「割り切り」です。

だけど、
数十枚(10枚)を超えると、無理(むり)だよ!
自動化せねばならぬ。。

自動化するにはどうすればいいのか、
いくつかの言語(Pythonとか)のPDF関係のライブラリーを試した結果、
R言語のpdftoolsで対応する事としました。

#

使い方(パッケージ版)


githubにパッケージを作ったのでインストールしてください。
準備.R
library(devtools) # install.packages("devtools")
install_github("nt1969m/sbitools",force=T) #面倒な事を聞かれたら、3: Noneで、  

PDFのあるファイルパスを指定し、実行して下さい。

CSV作成.R
# setwd() ※PDFのあるディレクトリーを設定
    # R本体の場合、  「メニュー」 → 「その他」 → 「作業ディレクトリの変更」
    # RStudioの場合、「メニュー」→「Session」→「Set Working Directory」→「Choose Directory」
d <- getwd()
library(sbitools) 
dummy <- Div(d) # 配当金の略語のつもり

CSVファイル"株式等配当金.csv"が作られたはず。
#

使い方(ソース直書き版)
※忘れてください。


銘柄名のみ全角で残し、残りを半角&型の調整
以下余白は削除
作業状況をファイル・ページ毎に出力します。
csv作成.R
source(	"B_0988_SBI証券_配当.R" ) 

	# PDF群のディレクトリーを指定
d	<-	file.path(	FY  ,"B_0988_SBI証券/配当"	)
  #FY   # 会計年度(Fiscal Year)のディレクトリ
配当 <- 配当.main( d ) 

write.table( 配当	
,file.path( d ,"配当_会計.txt"	) ,sep="," )
B_0988_SBI証券_配当.R
# pdfデータをインポートするため
 	library( pdftools )	# install.packages(	'pdftools'	)
	library( stringi )		# install.packages("stringi")# 全角

配当.main <- function( d ) {
		print( d )
	files <- dir(	d ,pattern = ".pdf$" ,ignore.case=T )

	stack <- 配当.init()
	for( a in files ) {
		f <- file.path( d ,a  )	# ファイル単位
			# 入力
		Pages	<- pdf_info( f )$pages	# 総ページ数
			print( paste( a ,Pages ) )	
		mei		<-	配当.pdf( pdf_data( f ) ,Pages )
		stack		<-	rbind( stack ,mei )
	}		
return( 配当.fin( stack ) )
}
print( c("配当.main()" ,配当.main ) )

配当.pdf <- function( df ,Pages ) {
# 配当金
	mei	<- 配当.init()	
	for( p in 1:Pages ) {
		mei[ p * 2 -1 ,] <-	配当.upper( df ,p )  
		mei[ p * 2     ,] <-	配当.lower(  df ,p )	 
			print( paste( " :" ,p ,substr( mei[ p * 2 -1,c(1:2) ] ,1 ,10 ) ,mei[ p * 2 ,c(1:2) ] ) )	
	}
return( mei )
}
print( c("配当.pdf()" ,配当.pdf ) )

配当.半角 <- function( mei ) {
		# 半角
	han	<- 配当.init()
					# stri_trans_nfkc( mei ) #NG
	for( i in 1:nrow( mei ) ) {
		han[ i ,1 ]	<-	mei [ i ,1 ] 
		han[ i ,-1 ]	<-	stri_trans_nfkc( mei [ i ,-1 ] )
	}
	han[ ,"お支払日"]			<-	as.Date( han[ ,"お支払日"	]		,format="%Y年%m月%d日")
	han[ ,"配当基準日"]	<-	as.Date( han[ ,"配当基準日"	]	,format="%Y年%m月%d日")
return( han )
}
print( c("配当.半角()" ,配当.半角 ) )

配当.fin <- function( stack ) {
	o <-	! is.na( stack[  ,"銘柄コード" ] )  # 以下余白を削除
	h_mei	<- 配当.半角( stack[ o, ] )
	h_mei[ ,"銘柄名"] 		<- substr( h_mei[ ,"銘柄名" ] ,1 ,10 ) 
	h_mei[ ,"銘柄コード"] 		<- gsub( "[()]" ,"" ,h_mei[ ,"銘柄コード"] ) 
	h_mei[ ,"配当単価"] 		<- as.integer( gsub( "," ,"" ,h_mei[ ,"配当単価"] ) )
	h_mei[ ,"数量"] 		<- as.integer( gsub( "," ,"" ,h_mei[ ,"数量"] ) )
	h_mei[ ,"配当金額"] 		<- as.integer( gsub( "," ,"" ,h_mei[ ,"配当金額"] ) )
	h_mei[ ,"所得税"]			<-	as.integer( gsub( "," ,"" ,h_mei[ ,"所得税"] ) )
	h_mei[ ,"地方税"]			<-	as.integer( gsub( "," ,"" ,h_mei[ ,"地方税"] ) )
	h_mei[ ,"端数処理代金"]			<-	as.integer( gsub( "," ,"" ,h_mei[ ,"端数処理代金"] ) )
	h_mei[ ,"お受取金額"]	<-	as.integer( gsub( "," ,"" ,h_mei[ ,"お受取金額"] ) )
return( h_mei )
}
print( c("配当.fin()" ,配当.fin ) )

配当.init	<- function()	{
# 最終型
	# 列数と列名を初期化
	配当金 <- data.frame( matrix( NA ,0 ,11 ) ) 
	colnames( 配当金 )		<-	c(
 "銘柄名"	,"銘柄コード"
,"お支払日"	 ,"配当単価" ,"数量"
,"配当金額"	,"所得税"	 ,"地方税" ,"端数処理代金"	,"お受取金額"
,"配当基準日" )
	return( 配当金 )		
}
print( c("配当.init()" ,配当.init ) )

# y抽出
配当.yn <- function( df ,p ,n )	{
	# p:ページ
	# n:明細行の"y"
	x <- paste0( df[[ p ]]
				[ df[[ p ] ]$"y" == n	,	]$"x"	)
	x <- as.integer( x )
	o <- order( c( x ) )
	t <- paste0( df[[p] ]
				[ df[[p] ]$"y" == n	,	]$"text"	)
	return( t[ o ] )
}
print( c("配当.yn()" ,配当.yn ) )

# 日付の対処
配当.ymd <- function( ve ) {
	d	<-	grep(		"日"	,ve		)	
 	if( length( d ) != 1 )	return( ve )						# ベクトルの要素が「1」である事
	y	<-	grep(		"年"	,ve		)	
 	switch(	d	
 	,	"1"	= {
				 	if(	y == 1 ) {
				 		paste0( ve[ d ]	)							# 年月日 
				 	} else
				 		paste0( ve[ y ] ,ve[ d ]	)				# (月日) (年)	※欧米かよ
		}
 	,	"2"	= paste0( ve[1]	,ve[ d ]		)				# (年)月日 or (年月)日
 	,	"3"	= paste0( ve[1]	,ve[2]		,ve[ d ]		)	# (年)(月)(日)
	)
}
print( c("配当.ymd()" ,配当.ymd ) )

# 単価・数量の対処
配当.unit <- function( ve ) {
	u	<-	grep(		"."	,ve		)	
 	if( length( u ) != 1 )	return()						# ベクトルの要素が「1」である事
 	return( c( ve[u]	,ve[u+1] ) )				# "配当単価" 、"数量"
}
print( c("配当.unit()" ,配当.unit ) )

# 銘柄コードの対処
配当.code <- function( ve ) {
	n	<-	grep(		")"	,ve		)	
 	if( length( n ) != 1 )	return()						# ベクトルの要素が「1」である事
 	switch(	n	
 	,	"1"	= paste0( ve[1]	)							# "(NNNN)" 
 	,	"2"	= paste0( ve[1]	,ve[2]		)				# "(NNNN" ")" or "(" "NNNN)"
 	,	"3"	= paste0( ve[1]	,ve[2]		,ve[3]		)	# "(" "NNNN" ")"
	)
}
print( c("配当.code()" ,配当.code ) )

配当.name <- function( ve ) {
	# 銘柄名の対処
 	switch(	length( ve )	
 	,	"1"	= paste( ve[ 1 ] )				# "X" 
 	,	"2"	= paste( ve[ 1 ] ,ve[ 2 ] )		# "X" and"YY"
 	)
}
print( c("配当.name()" ,配当.name ) )

# 上段
配当.upper	<- function( df ,p )	{
	# p : ページ
	y1 <- 配当.yn( df ,p ,91 )
	y2 <- 配当.yn( df ,p ,100 )
	y3 <- 配当.yn( df ,p ,94 )
	y4 <- 配当.yn( df ,p ,126 )
	y5 <- 配当.yn( df ,p ,139 )
y1		<-	   配当.name( y1 )		# "X" と "YY" を結合
y2		<-	   配当.code( y2 )		# "(nnnn" と ")" を結合
y3 	<- c(	配当.ymd( y3 )	,配当.unit(	y3 )	)
y5 	<-		配当.ymd(y5)
	return( c( y1 ,y2 ,y3 ,y4 ,y5 ) )
}
print( c("配当.upper()" ,配当.upper ) )

# 下段
配当.lower	<- function( df ,p )	{
	# p : ページ
	y6 <- 配当.yn( df ,p ,166 )
	y7 <- 配当.yn( df ,p ,175 )
	y8 <- 配当.yn( df ,p ,171 )
	y9 <- 配当.yn( df ,p ,202 )
	y10 <- 配当.yn( df ,p ,216 )
y6		<-	   配当.name( y6 )		# "X" と "YY" を結合
y7		<-	    配当.code( y7 )
y8 	<- c(	配当.ymd( y8 )	,配当.unit( y8 )	)
y10	<-		配当.ymd(y10)
# 返り値
	r <- c( y6 ,y7 ,y8 ,y9 ,y10 )
	n <- length( r )
	if	(	n !=	11 	)	{	
		return( c( r ,rep( NA ,11-n ) ) )
	} else { 			# 明細行であれば
		return( r )
	}
}
print( c("配当.lower()" ,配当.lower ) )

#

pdftoolsとは


pdftools - CRAN

の、ようです。

まずはインストール

pdftools_導入.R
>   library(	pdftools	) # install.packages('pdftools')
 警告メッセージ: 
 パッケージ pdftools はバージョン 3.5.2  R の下で造られました  
感謝した記事
⭐️PDFの情報・文章をRでごっそり取得する https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&ved=2ahUKEwjJ9O7s4uTrAhUMMd4KHYmiAawQFjACegQIARAB&url=https%3A%2F%2Furibo.hatenablog.com%2Fentry%2F2016%2F02%2F27%2F195500&usg=AOvVaw0jOaR0QX2AbvggqgdelGAR

#

PDFを分析

PDF_分析.r
> f	<-	
 file.path(
  FY # 会計年度(Fiscal Year)のディレクトリ
  ,"B_0988_SBI証券/配当" # 中間のディレクトリ
 ,"なんちゃら.PDF"	) # ファイル名

> pdf_data( f )
[[1]]
# A tibble: 44 x 6
   width height     x     y space text                  
   <int>  <int> <int> <int> <lgl> <chr>                 
 1    14      6   482    10 FALSE 1/                  
 2    28      6   518    10 FALSE ページ              
 3    64      6   460    19 TRUE  作成日:2020    
 4    14      6   532    19 FALSE                   
 5   132     11   199    15 FALSE 株式等配当金のお知らせ
 6    36      8    21    45 FALSE 有限会社              
 7    54      8    66    45 FALSE ○○○○○○○○          
 8     9      8   138    45 FALSE                     
 9    21      6   273    64 FALSE Znn                
10    79      6    28    91 FALSE SBIホールディングス
# … with 34 more rows

# 全部見たいので、テキスト出力
write.table(
  pdf_data( f )
 ,gsub(	".PDF"	,".txt"	,f )	)

## ちなみに、地道に全部見るなら、こうなる。
 pdf_data( f )[[1]][11:44,]
 pdf_data( f )[[1]][21:44,]
 pdf_data( f )[[1]][31:44,]
 pdf_data( f )[[1]][41:44,]
なんちゃら.txt
"width" "height" "x" "y" "space" "text"
"1" 14 6 482 10 FALSE "1/"
"2" 28 6 518 10 FALSE "1ページ"
"3" 64 6 460 19 TRUE "作成日:2020年"
"4" 14 6 532 19 FALSE "6月"
"5" 132 11 199 15 FALSE "株式等配当金のお知らせ"
"6" 36 8 21 45 FALSE "有限会社"
"7" 54 8 66 45 FALSE "○○○○○○○○"
"8" 9 8 138 45 FALSE "様"
"9" 21 6 273 64 FALSE "Znn"
"10" 79 6 28 91 FALSE "SBIホールディングス"
"11" 36 6 36 100 FALSE "(8473"
"12" 7 6 86 100 FALSE ")"
"13" 43 6 86 126 FALSE "48,000"
"14" 14 6 554 19 FALSE "5日"
"15" 35 6 251 94 FALSE "2020年"
"16" 43 6 331 64 FALSE "726320"
"17" 14 6 295 94 FALSE "6月"
"18" 35 6 194 126 FALSE "7,351"
"19" 35 6 266 139 FALSE "2020年"
"20" 172 6 395 64 FALSE "nnnnnnnnnnnnnnnnnnnnnnnn"
"21" 14 6 316 94 FALSE "8日"
"22" 71 6 374 94 FALSE "80.0000000"
"23" 21 6 540 94 FALSE "600"
"24" 7 6 323 126 FALSE "0"
"25" 7 6 439 126 FALSE "0"
"26" 43 6 518 126 FALSE "40,649"
"27" 35 6 309 139 FALSE "3月31日"
"28" 28 6 28 171 FALSE "以下余白"
"29" 43 6 518 229 FALSE "40,649"
"30" 270 8 21 251 FALSE "◎端数処理代金につきましては、特定口座における譲渡所得等の計"
"31" 261 8 30 260 FALSE "算対象とはならないため確定申告が必要となる場合があります。"
"32" 252 8 30 269 FALSE "本お知らせは大切に保管していただき、確定申告時の手続きに"
"33" 189 8 30 278 FALSE "つきましては税務署等にお問い合わせ下さい。"
"34" 151 7 21 298 TRUE "nnnnnnnnnnnnnnnnnnnnn"
"35" 93 7 179 298 FALSE "xxxxxxxxxxxxx"
"36" 266 7 21 307 FALSE "nnnnnnnnnnnnSTWHABnnnP#ZNNnnnnnnnnnnn"
"37" 45 8 331 296 FALSE "(取引店)"
"38" 9 8 385 296 FALSE "イ"
"39" 9 8 403 296 FALSE "ン"
"40" 9 8 421 296 FALSE "タ"
"41" 9 8 439 296 FALSE "ー"
"42" 9 8 457 296 FALSE "ネ"
"43" 9 8 475 296 FALSE "ッ"
"44" 9 8 493 296 FALSE "ト"

#

テキスト抽出


欲しいテキストは下記の通り。
0 行1 行2 行3 行4 行5
SBI記号→ (nnnn) (c) (g)
SBI列名→ 銘柄名 (銘柄コード) お支払日 配当金額 配当基準日
y ↓ あとで 説明するが 1頁 2明細
上段 91 100 94 126 139
下段 166 175 171 202 216

##

xとy(3列と4列)

サンプル(なんちゃら.txt)の3列と4列が、
xとy、
これの意味するところは、テキスト(text)の表示位置かと。
下記↓表が見た目のイメージ。
位置 テキスト
x→   横の位置
y↓    
上段
91 銘柄名
94 お支払日、配当単価(A)、数量(B)
100 (銘柄コード)
126 配当金額(税引前)(C)、所得税(D)、地方税(E)、端数処理代金(F)、お受取金額(G)
139 配当基準日
下段 明細が無い場合
166   銘柄名
171  以下余白  お支払日など
175 (銘柄コード)
202 (C)等
216 配当基準日
縦の位置

##

y(4列)を頼りにテキストを抽出

冗長になるので、一旦(テンポラリー)dfという変数に保存。
保存.R
# (前出)
write.table(
  pdf_data( f )
 ,gsub(	".PDF"	,".txt"	,f )	)
# (前出)閉じる

df <- pdf_data(	f )
# df:データフレーム(Data Frame)にコピー(名前は任意)

yごと(別、毎)にテキストを抽出

y抽出.R
# y抽出
yn <- function( p ,n )	{
	# p:ページ
	# n:明細行の"y"
	paste0(
	  df[ [p] ]
	[ df[ [p] ]$"y" == n , ]$"text"
	)
}
			# 上段
y1 <- yn( 1 ,91 )
y2 <- yn( 1 ,100 )
y3 <- yn( 1 ,94 )
y4 <- yn( 1 ,126 )
y5 <- yn( 1 ,139 )
			# 下段
y6 <- yn( 1 ,166 )
y7 <- yn( 1 ,175 )
y8 <- yn( 1 ,171 )
y9 <- yn( 1 ,202 )
y10 <- yn( 1 ,216 )
				# 目検(目視にて検証)
> c( y1 ,y2 ,y3 ,y4 ,y5 )
 [1] "SBIホールディングス" "(8473"             ")"                    
 [4] "2020年"             "6月"                   "8日"                  
 [7] "80.0000000"   "600"                 "48,000"          
[10] "7,351"             "0"                     "0"                    
[13] "40,649"           "2020年"             "3月31日"            
> c( y6 ,y7 ,y8 ,y9 ,y10 )
[1] "以下余白"

見づらいので、「日付」と「銘柄コード」を結合

トリミング.R
# 日付の対処
ymd <- function( df ) {
        # 「日」はどこにあるの?(要素数)
	d	<-	grep( "日" ,df )	
		# ベクトルの要素が「1」である事
 	if( length( d ) != 1 )	return()	
		# 日付を表示するにも、いくつものパターン有り
	switch(	d	
				      # 年月日 
 	,	"1"	= paste0( df[1]	)
        			  # (年)月日 or (年月)日
 	,	"2"	= paste0( df[1]	,df[2] )
				      # (年)(月)(日)
 	,	"3"	= paste0( df[1]	,df[2] ,df[3] )	
	)
}
# 銘柄コードの対処
code <- function( df ) {
        # 「)」はどこにあるの?(要素数)
	n <- grep( ")" ,df )	
 		# ベクトルの要素が「1」である事
 	if( length( n ) != 1 )	return() # 何もしない
	switch(	n	
				# "(NNNN)" 
 	, "1" = paste0( df[1] )
				# "(NNNN" ")" or "(" "NNNN)"
	, "2" = paste0( df[1] ,df[2] )	
				# "(" "NNNN" ")"
 	, "3" = paste0( df[1] ,df[2] ,df[3]  )
	)
}

	# 上段
y2	<-	code( y2 )	# "(nnnn" と ")" を結合
y3	<- c( ymd( y3 ) ,tail(	y3 ,2 )	)
y5	<-	ymd(y5)
	# 下段
if	( length( y6 ) != 0 ) {
	# 下段が明細行であれば(以下余白では無い場合)
	y7 <- 	 code( y7 )	# "(nnnn" と ")" を結合
	y8 	<- c( ymd( y8 ) ,tail( y8 ,2 )	)
	y10	<-    ymd(y10)
}

> 				# 目検(目視にて検証)
> c( y1 ,y2 ,y3	,y4 ,y5	 )
 [1] "SBIホールディングス" "(8473)"           "2020年6月8日"    
 [4] "80.0000000"   "600"                 "48,000"          
 [7] "7,351"             "0"                     "0"                    
[10] "40,649"           "2020年3月31日"  
> c( y6 ,y7 ,y8	,y9 ,y10 )
[1] "以下余白"

#

CSVを作りましょう!

全角.R
mei <- data.frame( matrix(NA,0,11 )) # 列数のみ重要
 # 列名、名前を書いときましょう。
colnames( mei )	 <- c( "銘柄名"	,"銘柄コード"
,"お支払日" ,"配当単価" ,"数量"
,"配当金額" ,"所得税" ,"地方税" ,"端数処理代金"	,"お受取金額"
,"配当基準日" )

# 型ができたので、中身を入れる。
mei[ 1 , ] <- c( y1 ,y2 ,y3 ,y4 ,y5 )
	# まずは上段、次は下段
if ( length(y6) == 0 ){	
	mei[ 2 , 1] <-	y8 # 以下余白の場合
} else				# 上段と同様に 
	mei[ 2 , ] <- c( y6 ,y7	,y8 ,y9	,y10 )

write.table( mei 
,gsub( ".PDF" ,"_全角.txt" ,f ) 
)
なんちゃら_全角.txt
"銘柄名" "銘柄コード" "お支払日" "配当単価" "数量" "配当金額" "所得税" "地方税" "端数処理代金" "お受取金額" "配当基準日"
"1" "SBIホールディングス" "(8473)" "2020年6月8日" "80.0000000" "600" "48,000" "7,351" "0" "0" "40,649" "2020年3月31日"
"2" "以下余白" NA NA NA NA NA NA NA NA NA NA
感謝した記事
Rでよくひっかかる、NAやlogical(0)、そのほかエラーの取り扱い https://yamakita.hatenablog.com/entry/20130111/1357867987

#

全角という高い壁


アイム、ジャッパァニィズゥ! オゥケィ?
(I am Japanese! OK?)

日本人たるもの、
「全角」という高い壁を乗り越えねば、
「半角」とは戦えまい。

選択肢は2択

全角_導入.R
# 全角のパッケージ
# 〜ジ !
library( stringi ) # install.packages("stringi")
# 〜ガ !
library( stringr ) # install.packages("stringr")

選択 : 〜ジ

半角ヴァージョン(version)のCSVを作ります。

半角.R
# 半角
h_mei <- mei
		# stri_trans_nfkc( mei ) #NG
h_mei[1,]	<-	stri_trans_nfkc( mei [1, ] )
h_mei[2,]	<-	stri_trans_nfkc( mei [2, ] )
# 目検(目視にて検証)
> h_mei
               銘柄名 銘柄コード     お支払日   配当単価 数量 配当金額 所得税
1 SBIホールディングス     (8473) 2020年6月8日 80.0000000  600   48,000  7,351
2            以下余白       <NA>         <NA>       <NA> <NA>     <NA>   <NA>
  地方税 端数処理代金 お受取金額    配当基準日
1      0            0     40,649 2020年3月31日
2   <NA>         <NA>       <NA>          <NA>

# 日付を変換
h_mei[ ,"お支払日"] <- 
	as.Date( h_mei[ ,"お支払日" ] ,format="%Y年%m月%d日"
    )
h_mei[ ,"配当基準日"] <-
	as.Date( h_mei[ ,"配当基準日" ],format="%Y年%m月%d日"
	)
# 目検(目視にて検証)
> h_mei
               銘柄名 銘柄コード   お支払日   配当単価 数量 配当金額 所得税 地方税
1 SBIホールディングス     (8473) 2020-06-08 80.0000000  600   48,000  7,351      0
2            以下余白       <NA>       <NA>       <NA> <NA>     <NA>   <NA>   <NA>
  端数処理代金 お受取金額 配当基準日
1            0     40,649 2020-03-31
2         <NA>       <NA>       <NA>

write.table( h_mei	
,gsub(	".PDF"	,"_半角.txt"	,f	)	)

なんちゃら_半角.txt
"銘柄名" "銘柄コード" "お支払日" "配当単価" "数量" "配当金額" "所得税" "地方税" "端数処理代金" "お受取金額" "配当基準日"
"1" "SBIホールディングス" "(8473)" 2020-06-08 "80.0000000" "600" "48,000" "7,351" "0" "0" "40,649" 2020-03-31
"2" "以下余白" NA NA NA NA NA NA NA NA NA NA
感謝した記事
2017-10-12 Rで全角英数記号を半角にするのに{stringi}が役に立った話 https://pediatricsurgery.hatenadiary.jp/entry/2017/10/12/105242

{stringr}/{stringi}とbaseの文字列処理について
https://rstudio-pubs-static.s3.amazonaws.com/92478_6704b96865e449b4bad7acb71443c8bc.html#文字列連結と分割str_cstr_split

#

大量データ


手元にある1年分のデータ(47ファイル)でテストしました。
前出のプログラムに手を入れて、こんな感じになりました。

##

ファイル単位
ファイル単位.R
# ファイル名
f <- file.path(
  FY   # 会計年度(Fiscal Year)のディレクトリ
  ,"B_0988_SBI証券/配当"  # 中間のディレクトリ
 ,"なんちゃら.PDF"
) 

# PDF → CSV
mei	<-	配当金( f )

# _全角csv
write.table( mei ,gsub(	".PDF" ,"_全角.txt" ,f )	)

# 半角 ← 全角
h_mei	<- 半角( mei )
# _半角csv
write.table( h_mei ,gsub( ".PDF" ,"_半角.txt" ,f	) )

##

ディレクトリー単位
ディレクトリー単位.R
# PDF群のディレクトリー
d <- file.path(	FY ,"B_0988_SBI証券/配当" ) 

files <- dir( d ,pattern = ".pdf$" ,ignore.case=T )

stack <- init()
for( a in 1:length( files ) ) {
	f <- file.path( d ,files[ a ] )	# ファイル単位
	mei	<- 配当金( f )
	stack	<- rbind( stack ,mei )
}		
# _全角csv
write.table( stack ,file.path( d ,"配当_全角.txt"	) )

# 全角 → 半角
h_mei	<- 半角( stack )

# 照合
sum( as.integer( gsub( "," ,"" ,h_mei[ ,"配当金額"] ) ) ,na.rm=T )
sum( as.integer( gsub( "," ,"" ,h_mei[ ,"所得税"] ) ) ,na.rm=T )
sum( as.integer( gsub( "," ,"" ,h_mei[ ,"お受取金額"] ) ) ,na.rm=T )

# _半角csv
write.table( h_mei ,file.path( d ,"配当_半角.txt" ) )

##

まとめ
B_0988_SBI証券_配当.R
# pdfデータをインポートするため
 	library(	pdftools	)
# 全角→半角
	library( stringi ) # install.packages("stringi")
#	library( stringr ) # install.packages("stringr")

# 最終型
init	<- function()	{
# 列数と列名を初期化
	配当金 <- data.frame( matrix( NA ,0 ,11 ) )
	colnames( 配当金 )		<-	c(
 "銘柄名"	,"銘柄コード"
,"お支払日"	 ,"配当単価" ,"数量"
,"配当金額"	,"所得税"  ,"地方税" ,"端数処理代金" ,"お受取金額"
,"配当基準日" )
	return( 配当金 )		
}
# y抽出
yn <- function( df ,p ,n )	{
	# p:ページ
	# n:明細行の"y"
	x <- paste0( df[[ p ]]
				[ df[[ p ] ]$"y" == n , ]$"x"	)
	x <- as.integer( x )
	o <- order( c( x ) )
	t <- paste0( df[[ p ] ]
				[ df[[ p ] ]$"y" == n , ]$"text"	)
	return( t[ o ] )
}
# 日付の対処
ymd <- function( ve ) {
	d	<-	grep(		"日"	,ve		)	
 	if( length( d ) != 1 )	return( ve )						# ベクトルの要素が「1」である事
	y	<-	grep( "年" ,ve )	
 	switch(	d	
 	,	"1"	= {
		 if( y == 1 ) {
			paste0( ve[ d ]	)	# 年月日 
		} else
			paste0( ve[ y ] ,ve[ d ] ) 
		# (月日) (年)	※欧米かよ
		}
 	,	"2"	= paste0( ve[1]	,ve[ d ])
		# (年)月日 or (年月)日
 	,	"3"	= paste0( ve[1]	,ve[2] ,ve[ d ]	)
		# (年)(月)(日)
	)
}
# 単価・数量の対処
unit <- function( ve ) {
	u	<- grep( "." ,ve )	
 	if( length( u ) != 1 )	return()						# ベクトルの要素が「1」である事
 	return( c( ve[u] ,ve[u+1] ) ) # "配当単価" 、"数量"
}
# 銘柄コードの対処
code <- function( ve ) {
	n	<- grep( ")" ,ve )	
 	if( length( n ) != 1 )	return()						# ベクトルの要素が「1」である事
 	switch(	n	
 	,	"1"	= paste0( ve[1]	)
	# "(NNNN)" 
 	,	"2"	= paste0( ve[1]	,ve[2] )
	# "(NNNN" ")" or "(" "NNNN)"
 	,	"3"	= paste0( ve[1]	,ve[2] ,ve[3] )
	# "(" "NNNN" ")"
	)
}
# 銘柄名の対処
name <- function( ve ) {
 	switch(	length( ve )	
 	,	"1"	= paste( ve[ 1 ] )				# "X" 
 	,	"2"	= paste( ve[ 1 ] ,ve[ 2 ] )		# "X" and"YY"
 	)
}
# 上段
upper	<- function( df ,p )	{
	# p : ページ
	y1 <- yn( df ,p ,91 )
	y2 <- yn( df ,p ,100 )
	y3 <- yn( df ,p ,94 )
	y4 <- yn( df ,p ,126 )
	y5 <- yn( df ,p ,139 )
y1		<-	   name( y1 ) # "X" と "YY" を結合
y2		<-	   code( y2 ) # "(nnnn" と ")" を結合
y3 	<- c(	ymd( y3 )	,unit(	y3 )	)
y5 	<-		ymd(y5)
	return( c( y1 ,y2 ,y3 ,y4 ,y5 ) )
}
# 下段
lower	<- function( df ,p )	{
	# p : ページ
	y6 <- yn( df ,p ,166 )
	y7 <- yn( df ,p ,175 )
	y8 <- yn( df ,p ,171 )
	y9 <- yn( df ,p ,202 )
	y10 <- yn( df ,p ,216 )
y6		<-   name( y6 ) # "X" と "YY" を結合
y7		<-    code( y7 )
y8 	<- c(	ymd( y8 )	,unit( y8 )	)
y10	<-		ymd(y10)
# 返り値
	r <- c( y6 ,y7 ,y8 ,y9 ,y10 )
	n <- length( r )
	if	(	n !=	11 	)	{	
		return( c( r ,rep( NA ,11-n ) ) )
	} else { 			# 明細行であれば
		return( r )
	}
}
# 配当金
配当金 <- function( f ) {
# 入力
	Pages	<- pdf_info( f )$pages	# 総ページ数
	df	<-	pdf_data( f )
# 出力
	mei	<- init()	
	for( p in 1:Pages ) {
		mei[ p * 2 -1 ,] <- upper( df ,p )  
		mei[ p * 2    ,] <- lower( df ,p )	 
	}
	return( mei )
}
# 半角
半角 <- function( mei ) {
	han	<- init()
		# stri_trans_nfkc( mei ) #NG
	for( i in 1:nrow( mei ) ) {
		han[ i , ] <- stri_trans_nfkc( mei [ i , ] )
	}
	han[ ,"お支払日"]   <- as.Date( han[ ,"お支払日"	] ,format="%Y年%m月%d日")
	han[ ,"配当基準日"] <- as.Date( han[ ,"配当基準日"	] ,format="%Y年%m月%d日")
return( han )
}

以 上

4
4
8

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?