【VBA】マクロで時短!データ分割&抽出データ一括編集は小技マクロで簡略化【Yahoo!ショッピング出店者向け】

02.8.2022

Yahoo!ショッピングでプロフェショナル出店すると取り扱える商品数が無制限です。
商品数により費用が変動することはありません。通販サイトに出店する場合、契約プランによって取り扱いできる商品数が制限があることも多く、無制限というのはメリットのひとつといえるでしょう。

自店で販売する商品の種類が少なく、制限数に収まる場合は全く問題ありませんが、ジャンルに幅のある総合通販やドロップシッピング(無在庫販売)などで商品数がたくさんある場合には有効となります。

私は家族経営の販路拡大としてYahoo!ショッピングに出店しており、ドロップシッピングを採用しているのですが、商品管理を自動化してはいるものの細かい修正などは自動化ではまかなえないことがあります。

商品情報修正は基本的にはcsvデータで行うのですが、商品数が多いとデータ数が多くなり、アップロードする時に件数制限に引っかかってしまう場合があります。

そこで、データ分割や商品データ編集のためちょっとした小技的な便利マクロを作りました。

csvデータ分割マクロ

Yahoo!ショッピングの仕様上、csv商品データを利用して更新する場合、商品管理ページからのアップロードではデータ数2万件以下、FTPアップロードでは10万件以下という制限があります。

2万件でもかなり多いと思うので、おそらくほとんどのお店では影響ないかなと思いますが、私が出店している環境ではドロップシッピング採用により30万件以上の商品データがあります。

30万件更新するには、2万件ごとにファイル分けする必要があるのですが、ファイルを新規作成して、2万行コピーペーストして保存してを一定数繰り返さないといけません。かなり手間がかかり面倒です。

これを自動化したのが以下のマクロです。
このままデータのあるcsvファイル上で実行してもらえれば動くと思います。

Sub SplitDataToNewBook()
    Dim Ws As Worksheet, Wb As Workbook
    Dim Fname, dt, actPath As String
    Dim lTotal, lNum, i, lStartRow As Long
    
    '★ブックごとにコピーする行数を指定
    Const CpRow = 20000
    
    'Y!のFTPアップロードファイル名ルール対応
    dt = Format(Date, "yyyymmdd")
    Set Ws = ActiveSheet
    
    'アクティブファイルパス取得
    actPath = ActiveWorkbook.Path
    
    '総行数
    lTotal = Ws.UsedRange.Rows.Count - 1
    
    '行数に応じてループする回数を計算(割り切れない場合は+1回)
    lNum = Int(lTotal / CpRow) + IIf(lTotal Mod CpRow > 0, 1, 0)
    
    lStartRow = 2
    
    '画面更新要否(する:True、しない:False(処理速度対策))
    Application.ScreenUpdating = False
    For i = 1 To lNum

        '新規ブック作成
        Set Wb = Workbooks.Add
        
        'ファイル名に日付と6桁0埋めで連番付与
        Fname = "data_spy" & dt & Format(i, "000000") & ".csv"
        
        'コピー処理
        Ws.Rows(1).Copy Wb.Worksheets("Sheet1").Range("A1")
        Ws.Rows(lStartRow & ":" & lStartRow + CpRow - 1).Copy Wb.Worksheets("Sheet1").Range("A2")
        
        '同一フォルダにcsv形式で保存
        Wb.SaveAs Filename:=actPath & "\" & Fname, FileFormat:=xlCSV
        Wb.Close
        Set Wb = Nothing
        lStartRow = lStartRow + CpRow
    Next i
    
    Application.ScreenUpdating = True
End Sub

上記マクロを全商品のcsvデータ上で実行すれば、指定したデータ数(行数)毎に新しくファイルが作成されます。30万件あれば、2万行のデータが15ファイルできます。端数が出れば端数行の1ファイルが追加で作成されます。

やっていることは、全件数(データ総行数)の数字から2万行で割ることによりループ数を割り出し、1ループごとに2万行を新しいファイルにコピーして保存。これを繰り返しているシンプルなマクロです。

「CpRow」の数字を変えてもらえれば、指定したデータ数に分割されたファイルが作成されます。
(コードの★マークのところ)
例:50000(30万行のデータで実行すると5万行のデータが6ファイル)

FTPアップロードの場合にはファイル名にルールがあるので、そちらにも対応できるファイル名で出力できるようにしています。ルールというのは、アップロードしたデータの本番環境への反映方法です。

ファイル名は「data_spyYYYYMMDDhhmmss.csv」の形式の必要があります。
既存商品データの項目修正を指定する「data_spy」、
本番環境へ反映予約時間を指定する「YYYYMMDDhhmmss」です。
※西暦(YYYY)月(MM)日(DD)時(hh)分(mm)秒(ss)

予約時間は指定しなくても大丈夫なのですが、複数ファイルを一括でアップロードすることを前提としているため、ファイル名を被らせないという意味でも付与しています。
また、このファイル名はマクロ実行時の日付にループ数を付与(連番)しているだけであり、正確な時間を指定するものではありませんが、アップロード後にすでに指定時間を過ぎていた場合は、ファイルの読み込みが終わり次第、順次反映される仕様のため特に問題はありません。

後は、できたファイルを商品管理からアップロードするか、FTPソフトにドラッグアンドドロップして反映を待つだけです。

商品価格一括設定

Yahoo!ショッピングのストア管理サイトであるストアクリエイターProから、登録している全ての商品データをcsv形式でダウンロードできるので、エクセルで一括処理したい時などに利用します。
ですが、たまに更新するくらいでであれば手動処理でも問題ないかもしれませんが、データ数が増えてきたり、更新頻度が増えてきたりすると毎回同じ処理を行わないといけなくなってしまいかなり煩わしい作業となってしまいます。

そこでマクロを作ることにしました。

Yahoo!ショッピングが設定するある条件を満たせばYahoo!プレミアム会員限定の価格を設定できるフィールド「member-price」が使えるようになるのですが、私はこのフィールドを商品ページの更新や、キャンペーンなどで変更が入ったりした場合に、都度更新していたのですが本マクロを使うようになり手間が省けました。

更新処理を簡略化したのが以下のマクロです。
注意としては、商品コード「code」で設定するデータを抽出しているので、ある程度の商品コード命名規則が確立している必要があります。

Sub EditPriceForYPreMember()
    Dim Ws As Worksheet
    Dim sActPath, sActFName, sEditFName As String
    Dim i, lNCol, lValRows As Long
    Dim t As String

    sActPath = ActiveWorkbook.Path
    sActFName = ActiveWorkbook.Name
    sEditFName = "data_spy.csv"
    
    If Dir(sActPath & "\" & sEditFName) <> "" Then
        MsgBox "処理後に作成されるファイルと同名のファイル「" _
                & sEditFName & "」あるよ" & vbCrLf _
                & "移動またはファイル名変更お願い"
        Exit Sub
    End If
    
    Set Ws = ActiveSheet

    '画面更新要否(する:True、しない:False(処理速度対策))
    Application.ScreenUpdating = False
    '確認メッセージをOFF
    Application.DisplayAlerts = False

    '1行目(見出し)の最終列を取得して列数を算出
    lNCol = Ws.Cells(1, Columns.Count).End(xlToLeft).Column

    '編集済み(2列になっている)なら終了
    If lNCol < 3 Then
        GoTo ENDEDIT:
    End If
    
    '最終列からループ
    For i = lNCol To 1 Step -1
        '1行目の項目名が「code」か「price」以外はその列を削除
        If Not Ws.Cells(1, i) = "code" And Not Ws.Cells(1, i) = "price" Then
            Ws.Cells(1, i).EntireColumn.Delete
        End If
    Next

    '「id-」から始まる商品コード以外をフィルター
    Ws.Range("A1").AutoFilter Field:=1, Criteria1:="<>id-*"
    
    'フィルター結果がある場合(表示結果が1つ以上)
    If Ws.Cells(Rows.Count, 1).End(xlUp).Row > 1 Then
        'フィルター結果を削除
        Ws.Range("B1").CurrentRegion.Resize(Rows.Count - 1).Offset(1, 0).Delete
    End If

    'フィルターを解除
    Ws.Range("A1").AutoFilter
    
    'フィルター処理後のデータがない場合は終了
    lValRows = Ws.Cells(Rows.Count, 1).End(xlUp).Row - 1
    If lValRows < 1 Then
        GoTo ENDEDIT:
    End If
    
    '数式代入による価格計算
    Ws.Range("C2").Formula = "=ROUNDDOWN(B2*0.9,0)"
    'データが一つであれば数式コピーしない
    If Not lValRows = 1 Then
        Ws.Range("C2:C" & lValRows + 1).FillDown
    End If
    '数式→値変換
    Ws.Range("C2:C" & lValRows + 1).Value = Ws.Range("C2:C" & lValRows + 1).Value

    'B列更新
    Ws.Cells(1, 3).Value = "member-price"
    Ws.Cells(1, 2).EntireColumn.Delete

ENDEDIT:
    Application.DisplayAlerts = True
    Application.ScreenUpdating = True
    
    ActiveWorkbook.SaveAs Filename:=sActPath & "\" & sEditFName, FileFormat:=xlCSV
    ActiveWorkbook.Close
    
    '元ファイルを削除
    Kill sActPath & "\" & sActFName

    Set Ws = Nothing
    MsgBox "Finish!"
End Sub

実行すると以下のような内容に編集されます。

実行前(ストアクリエイターProからダウンロードした商品データ)

↓↓↓

実行後(ファイル名:「data_spy.csv」生成)


コード内のコメントで簡単な説明をつけていますが、補足すると、コード冒頭の
If Dir(sActPath & “\" & sEditFName) <> “" Then
で、マクロ実行後に生成される「data_spy.csv」と被らないようにファイル存在チェックしています。

lNCol = Ws.Cells(1, Columns.Count).End(xlToLeft).Column
全列数を取得し、列数分を後のFor文でループします。

If Not Ws.Cells(1, i) = “code" And Not Ws.Cells(1, i) = “price" Then
ストアに登録済みの商品を更新するのであれば「code」と更新したいフィールドだけあればできるので、ループ内で「code」と「price」列以外を削除します。ここでは、「price」の値を元にプレミアム会員価格「member-price」を算出するため「price」を残しています。

Ws.Range(“A1″).AutoFilter Field:=1, Criteria1:="<>id-*"
フィルター機能を使って、処理したくない商品(ここでは「code」の値が「id-」以外の商品)を抽出します。フィルター条件はご自身の環境に合わせてください。
元々、1データずつ読み込んで判定していたのですが、フィルターを活用した方が処理時間が圧倒的に早かったです。

Ws.Range(“B1").CurrentRegion.Resize(Rows.Count – 1).Offset(1, 0).Delete
抽出結果を削除します。これらのメソッドを使うことで動的にデータ範囲を指定できるのですが、詳しくは各メソッド名や「フィルター結果 削除」などで検索をお願いします。
こうすることで、画像のように「ex-」から始まる商品は除外されます。除外する必要が無い場合は、フィルター処理しているところを全てコメントアウトしてください。

Ws.Range(“C2").Formula = “=ROUNDDOWN(B2*0.9,0)"
Formulaメソッドで数式を入力できるので「price」の値から自動的に計算されます。ここでは、ROUNDDOWN関数により10%引きで切り捨て計算しています。ROUNDUP関数(切り上げ)に変えたり、「0.9」の部分を変えて割引率も変えられます。
ちなみに、「member-price」が「price」より高ければ、アップロード後のデータチェック時にエラーになってしまいそのデータは反映されません。

Ws.Range(“C2:C" & lValRows + 1).FillDown
上記の数式を全データにコピーします。

Ws.Range(“C2:C" & lValRows + 1).Value = Ws.Range(“C2:C" & lValRows + 1).Value
数式を入れた時点ではあくまで数式なので、数式の結果を設定しています。
同じセルに.Valueすることで値に変換されます。

コード後半で、そのままFTPソフトなどでアップロードできるようファイル名を変更し、誤ってダウンロードしたファイルをそのままアップロードしてしまわないよう、ダウンロードしたファイルは「Kill」で削除しています。

ちなみに、先述しましたが、Yahoo!ショッピングストアへのアップロードには、アップロード方法に応じて1ファイルのデータ数に上限があります。このマクロで実行した後、上限を超えるようであれば先ほどの「csvデータ分割マクロ」を活用すればデータ分割も簡単です。 v( ̄∀ ̄)

まとめ

データを分割するというのは、様々な場所で便利になると思います。

Yahoo!ショッピングに限らず、本記事で紹介したマクロに条件分岐や別途処理などを追加して応用できるのではないかと思います。