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

2022-09-07 使い方の改善。setwd()、getwd()
2020-11-23 Rパッケージ化
<h1>やりたい事</h1>
法人税の決算作業で「受取配当金を集計する」のですが、

SBI証券の場合、元ネタがPDF形式なのですよ。
↓サンプル
![2020-09-13 9.24のイメージ.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374784/3ed48995-c317-dcd6-d2db-789421e84b3f.jpeg)

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

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

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

#<h1>使い方（パッケージ版）</h1>
githubにパッケージを作ったのでインストールしてください。

```r:準備.R
library(devtools) # install.packages("devtools")
install_github("nt1969m/sbitools",force=T) #面倒な事を聞かれたら、3: Noneで、  
```
PDFのあるファイルパスを指定し、実行して下さい。

```r:CSV作成.R
# setwd() ※PDFのあるディレクトリーを設定
    # R本体の場合、  「メニュー」 → 「その他」 → 「作業ディレクトリの変更」
    # RStudioの場合、「メニュー」→「Session」→「Set Working Directory」→「Choose Directory」
d <- getwd()
library(sbitools) 
dummy <- Div(d) # 配当金の略語のつもり
```
CSVファイル"株式等配当金.csv"が作られたはず。
#<h1>使い方（ソース直書き版）<br>※忘れてください。<br></h1>
銘柄名のみ全角で残し、残りを半角＆型の調整
以下余白は削除
作業状況をファイル・ページ毎に出力します。

```r: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="," )
```

```r: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 )						# ベクトルの要素が「１」である事
	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()						# ベクトルの要素が「１」である事
 	return( c( ve[u]	,ve[u+1] ) )				# "配当単価" 、"数量"
}
print( c("配当.unit()" ,配当.unit ) )

# 銘柄コードの対処
配当.code <- function( ve ) {
	n	<-	grep(		"）"	,ve		)	
 	if( length( n ) != 1 )	return()						# ベクトルの要素が「１」である事
 	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 ) )
```


#<h1>pdftoolsとは</h1>
pdftools - CRAN
https://cran.r-project.org/web/packages/pdftools/pdftools.pdf
の、ようです。

まずはインストール

```r:pdftools_導入.R
>   library(	pdftools	) # install.packages('pdftools')
 警告メッセージ: 
 パッケージ ‘pdftools’ はバージョン 3.5.2 の R の下で造られました  
```

<h6>感謝した記事</h6>
⭐️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

#<h1>PDFを分析</h1>
```r: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 １／                  
 2    28      6   518    10 FALSE １ページ              
 3    64      6   460    19 TRUE  作成日：２０２０年    
 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 Ｚnn                
10    79      6    28    91 FALSE ＳＢＩホールディングス
# … 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,]
```

```r:なんちゃら.txt
"width" "height" "x" "y" "space" "text"
"1" 14 6 482 10 FALSE "１／"
"2" 28 6 518 10 FALSE "１ページ"
"3" 64 6 460 19 TRUE "作成日：２０２０年"
"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 "Ｚnn"
"10" 79 6 28 91 FALSE "ＳＢＩホールディングス"
"11" 36 6 36 100 FALSE "（８４７３"
"12" 7 6 86 100 FALSE "）"
"13" 43 6 86 126 FALSE "４８，０００"
"14" 14 6 554 19 FALSE "５日"
"15" 35 6 251 94 FALSE "２０２０年"
"16" 43 6 331 64 FALSE "７２６３２０"
"17" 14 6 295 94 FALSE "６月"
"18" 35 6 194 126 FALSE "７，３５１"
"19" 35 6 266 139 FALSE "２０２０年"
"20" 172 6 395 64 FALSE "nnnnnnnnnnnnnnnnnnnnnnnn"
"21" 14 6 316 94 FALSE "８日"
"22" 71 6 374 94 FALSE "８０．０００００００"
"23" 21 6 540 94 FALSE "６００"
"24" 7 6 323 126 FALSE "０"
"25" 7 6 439 126 FALSE "０"
"26" 43 6 518 126 FALSE "４０，６４９"
"27" 35 6 309 139 FALSE "３月３１日"
"28" 28 6 28 171 FALSE "以下余白"
"29" 43 6 518 229 FALSE "４０，６４９"
"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 "ト"
```
#<h1>テキスト抽出</h1>
欲しいテキストは下記の通り。

|0 |行1|行2|行3|行4|行5|
|:--|:--|:--|:--|:--|:--|
| SBI記号→ ||(nnnn)||(c)|(g)|
| SBI列名→ |銘柄名|(銘柄コード)|お支払日|配当金額|配当基準日|
|y ↓|あとで|説明するが|１頁|２明細|だ|
|上段|91|100|94|126|139|
|下段|166|175|171|202|216|

##<h6>xとy（３列と４列）</h6>
サンプル（なんちゃら.txt）の３列と４列が、
xとy、
これの意味するところは、テキスト(text)の表示位置かと。
下記↓表が見た目のイメージ。

|位置|テキスト||
|:--|:--|:--|
|x→|　|横の位置|
|y↓|　|　|
|上段|||
| 91| 銘柄名||
| 94|        お支払日、配当単価(A)、数量(B)||
|100| (銘柄コード)||
|126| 配当金額（税引前）(C)、所得税(D)、地方税(E)、端数処理代金(F)、お受取金額(G)||
|139|配当基準日||
|下段|明細が無い場合||
|166|　|銘柄名|
|171|　以下余白　|お支払日など|
|175||(銘柄コード)|
|202||(C)等|
|216||配当基準日|
|縦の位置||

##<h6>y（４列）を頼りにテキストを抽出</h6>
冗長になるので、一旦（テンポラリー）dfという変数に保存。

```r:保存.R
# （前出）
write.table(
  pdf_data( f )
 ,gsub(	".PDF"	,".txt"	,f )	)
# （前出）閉じる

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

```
yごと（別、毎）にテキストを抽出

```r: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] "ＳＢＩホールディングス" "（８４７３"             "）"                    
 [4] "２０２０年"             "６月"                   "８日"                  
 [7] "８０．０００００００"   "６００"                 "４８，０００"          
[10] "７，３５１"             "０"                     "０"                    
[13] "４０，６４９"           "２０２０年"             "３月３１日"            
> c(　y6　,y7　,y8　,y9　,y10　)
[1] "以下余白"
```
見づらいので、「日付」と「銘柄コード」を結合

``` r:トリミング.R
# 日付の対処
ymd <- function( df ) {
        # 「日」はどこにあるの？（要素数）
	d	<-	grep(　"日"　,df　)	
		# ベクトルの要素が「１」である事
 	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 )	
 		# ベクトルの要素が「１」である事
 	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] "ＳＢＩホールディングス" "（８４７３）"           "２０２０年６月８日"    
 [4] "８０．０００００００"   "６００"                 "４８，０００"          
 [7] "７，３５１"             "０"                     "０"                    
[10] "４０，６４９"           "２０２０年３月３１日"  
> c( y6 ,y7 ,y8	,y9 ,y10 )
[1] "以下余白"
```
#<h1>CSVを作りましょう！</h1>

```r:全角.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 ) 
)
```

```r:なんちゃら_全角.txt
"銘柄名" "銘柄コード" "お支払日" "配当単価" "数量" "配当金額" "所得税" "地方税" "端数処理代金" "お受取金額" "配当基準日"
"1" "ＳＢＩホールディングス" "（８４７３）" "２０２０年６月８日" "８０．０００００００" "６００" "４８，０００" "７，３５１" "０" "０" "４０，６４９" "２０２０年３月３１日"
"2" "以下余白" NA NA NA NA NA NA NA NA NA NA
```

<h6>感謝した記事</h6>
Rでよくひっかかる、NAやlogical(0)、そのほかエラーの取り扱い
https://yamakita.hatenablog.com/entry/20130111/1357867987


#<h1>全角という高い壁</h1>
アイム、ジャッパァニィズゥ！　オゥケィ？
(I am Japanese! OK?)

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

選択肢は２択

```r:全角_導入.R
# 全角のパッケージ
# 〜ジ　！
library( stringi ) # install.packages("stringi")
# 〜ガ　！
library( stringr ) # install.packages("stringr")
```
選択　：　〜ジ

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

```r:半角.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	)	)

```
```r:なんちゃら_半角.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
```
<h6>感謝した記事</h6>
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


#<h1>大量データ</h1>
手元にある１年分のデータ（４７ファイル）でテストしました。
前出のプログラムに手を入れて、こんな感じになりました。

##<h6>ファイル単位</h6>

```r:ファイル単位.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	) )
```

##<h6>ディレクトリー単位</h6>

```r:ディレクトリー単位.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" ) )
```

##<h6>まとめ</h6>

```r: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 )						# ベクトルの要素が「１」である事
	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()						# ベクトルの要素が「１」である事
 	return( c( ve[u] ,ve[u+1] ) ) # "配当単価" 、"数量"
}
# 銘柄コードの対処
code <- function( ve ) {
	n	<- grep( "）" ,ve )	
 	if( length( n ) != 1 )	return()						# ベクトルの要素が「１」である事
 	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 )
}
```

以　上