diff --git a/XVBA/.vscode/settings.json b/XVBA/.vscode/settings.json new file mode 100644 index 00000000..77984130 --- /dev/null +++ b/XVBA/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "pleasanter-code-assist.enabled": false +} \ No newline at end of file diff --git a/XVBA/MSS/抽出マクロ.bas b/XVBA/MSS/抽出マクロ.bas new file mode 100644 index 00000000..7ee78ab0 --- /dev/null +++ b/XVBA/MSS/抽出マクロ.bas @@ -0,0 +1,370 @@ +Option Explicit + +Sub 明細の抽出() + If Range("選択ブランド").Value = "" Then + MsgBox "ブランドが選択されていません。", vbExclamation + Exit Sub + End If + + Application.ScreenUpdating = False + + Call 抽出シートクリア("抽出") + Call 明細情報抽出("サッシ工事", "抽出") + Call 明細情報抽出("内部建具工事", "抽出") + Call 明細情報抽出("設備工事", "抽出") + Call 明細情報抽出("雑工事", "抽出") + + Call 明細書シートに移動 + Call 明細書印刷範囲設定 + + Application.ScreenUpdating = True +End Sub + + +' filepath: c:\Users\k.nogi\#GitHub\ken_nogi\pleasanter\develop\##実行予算承認WF\sites\scripts\抽出マクロ.vbs +Sub 明細情報抽出(Byval categoryName As String, Byval destSheetName As String) + Dim srcWs As Worksheet, destWs As Worksheet + Dim srcTbl As ListObject + Dim destRow As Long, i As Long + Dim colProduct As Integer, colPrice As Integer, colQty As Integer, colUnit As Integer, colUnitName As Integer + Dim 金額 As Double, subtotal As Double + Dim lastRow As Long + Dim isFirst As Boolean + + '--- 対象のテーブル情報 --- + Dim srcSheetName As String + Dim srcTableName As String + srcSheetName = Range(categoryName).Value + srcTableName = Range(categoryName).Value + + '--- 設定 --- + Set srcWs = ThisWorkbook.Sheets(srcSheetName) + Set destWs = ThisWorkbook.Sheets(destSheetName) + Set srcTbl = srcWs.ListObjects(srcTableName) + + '列番号取得(列名は実際のものに合わせてください) + colProduct = srcTbl.ListColumns("商品名").Index + colPrice = srcTbl.ListColumns("単価").Index + colUnit = srcTbl.ListColumns("単位").Index + colQty = srcTbl.ListColumns("数量").Index + colUnitName = srcTbl.ListColumns("単位名").Index + + '--- データ書き込み開始行の決定 --- + lastRow = destWs.Cells(destWs.Rows.Count, 1).End(xlUp).Row + If destWs.Cells(1, 1).Value = "" Then + ' シートが空の場合 + destRow = 1 + isFirst = True + Else + destRow = lastRow + 1 + isFirst = False + End If + + '--- カテゴリ名・ヘッダー出力 --- + destWs.Cells(destRow, 1).Value = categoryName + destRow = destRow + 1 + + subtotal = 0 + + '--- データ抽出と金額計算 --- + For i = 1 To srcTbl.ListRows.Count + If srcTbl.DataBodyRange(i, colQty).Value > 0 Then + destWs.Cells(destRow, 1).Value = " " + srcTbl.DataBodyRange(i, colProduct).Value + destWs.Cells(destRow, 2).Value = srcTbl.DataBodyRange(i, colPrice).Value + destWs.Cells(destRow, 3).Value = srcTbl.DataBodyRange(i, colUnit).Value + destWs.Cells(destRow, 4).Value = srcTbl.DataBodyRange(i, colQty).Value + destWs.Cells(destRow, 5).Value = srcTbl.DataBodyRange(i, colUnitName).Value + 金額 = srcTbl.DataBodyRange(i, colPrice).Value * srcTbl.DataBodyRange(i, colUnit).Value * srcTbl.DataBodyRange(i, colQty).Value + destWs.Cells(destRow, 6).Value = 金額 + subtotal = subtotal + 金額 + destRow = destRow + 1 + End If + Next + + '--- 小計行(商品名と同じ列に"小計") --- + destWs.Cells(destRow, 1).Value = " 小計" + destWs.Cells(destRow, 6).Value = subtotal + + 'MsgBox "抽出と金額計算が完了しました", vbInformation +End Sub + +Sub 抽出シートクリア(Byval destSheetName As String) + Dim destWs As Worksheet + Set destWs = ThisWorkbook.Sheets(destSheetName) + destWs.Cells.ClearContents +End Sub + +Sub シートの切り替え() + Application.ScreenUpdating = False + '全シート非表示 + Call 全シート非表示 + + '必要なシートのみ表示 + Call 指定シート表示("サッシ工事") + Call 指定シート表示("内部建具工事") + Call 指定シート表示("設備工事") + Call 指定シート表示("雑工事") + + Application.ScreenUpdating = True +End Sub + +Sub 全シート非表示() + Dim sheetNames As Variant + Dim i As Integer + sheetNames = Array("NBサッシ工事", "NB内部建具", "NB設備", "B雑工事", "N雑工事", "Aサッシ工事", "A内部建具", "A設備", "A雑工事") + For i = LBound(sheetNames) To UBound(sheetNames) + On Error Resume Next + ThisWorkbook.Sheets(sheetNames(i)).Visible = xlSheetHidden + On Error Goto 0 + Next i +End Sub + +Sub 指定シート表示(Byval shName As String) + Dim sh As String + sh = Range(shName).Value + Dim ws As Worksheet + Set ws = ThisWorkbook.Sheets(sh) + ws.Visible = xlSheetVisible +End Sub + +Sub 基本入力シートに戻る() + Dim ws As Worksheet + Set ws = ThisWorkbook.Sheets("基本入力") + ws.Activate + ws.Range("A1").Select +End Sub + +Sub 見積書シートに移動() + Dim ws As Worksheet + Set ws = ThisWorkbook.Sheets("見積書") + ws.Activate + ws.Range("A1").Select +End Sub + +Sub 明細書シートに移動() + Dim ws As Worksheet + Set ws = ThisWorkbook.Sheets("明細書") + ws.Activate + ws.Range("A1").Select +End Sub + +Sub セル参照でシート移動(Byval sheetName As String) + Dim ws As Worksheet + Set ws = ThisWorkbook.Sheets(sheetName) + If ws.Visible = xlSheetHidden Or ws.Visible = xlSheetVeryHidden Then + Call シートの切り替え + End If + ws.Activate + ws.Range("F4").Select +End Sub + +Sub サッシ工事テーブルへ移動() + If Range("選択ブランド").Value = "" Then + MsgBox "ブランドが選択されていません。", vbExclamation + Exit Sub + End If + Call セル参照でシート移動(Range("サッシ工事").Value) +End Sub + +Sub 内部建具工事テーブルへ移動() + If Range("選択ブランド").Value = "" Then + MsgBox "ブランドが選択されていません。", vbExclamation + Exit Sub + End If + Call セル参照でシート移動(Range("内部建具工事").Value) +End Sub + +Sub 設備工事テーブルへ移動() + If Range("選択ブランド").Value = "" Then + MsgBox "ブランドが選択されていません。", vbExclamation + Exit Sub + End If + Call セル参照でシート移動(Range("設備工事").Value) +End Sub + +Sub 雑工事テーブルへ移動() + If Range("選択ブランド").Value = "" Then + MsgBox "ブランドが選択されていません。", vbExclamation + Exit Sub + End If + Call セル参照でシート移動(Range("雑工事").Value) +End Sub + +Sub クリア() + ActiveSheet.Range("F4:F10000").ClearContents +End Sub + + +Sub 見積書明細書PDF出力() + Dim wsMitsumori As Worksheet, wsMeisai As Worksheet + Dim pdfFileName As String + Dim folderPath As String + Dim mitsumoriNo As String, koujiName As String, issueDate As String + + Set wsMitsumori = ThisWorkbook.Sheets("見積書") + Set wsMeisai = ThisWorkbook.Sheets("明細書") + + ' 保存先フォルダ(必要に応じて変更) + folderPath = ThisWorkbook.Path & "\" + + ' ファイル名用情報取得 + mitsumoriNo = Range("見積書番号").Value + koujiName = Range("工事名").Value + issueDate = Range("発行年月日").Value + + ' 日付を"yyyyMMddHHmmss"形式に + Dim dt As String + dt = Format(issueDate, "yyyymmdd-HHMMSS") + + ' ファイル名作成 + pdfFileName = folderPath & mitsumoriNo & "■" & koujiName & "■" & dt & ".pdf" + + ' シートを配列で指定してPDF出力 + Sheets(Array("見積書", "明細書")).Select + ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:=pdfFileName, Quality:=xlQualityStandard + + ' 元のシートに戻る + Call 基本入力シートに戻る + + MsgBox "PDF出力が完了しました。" & vbCrLf & pdfFileName, vbInformation +End Sub + +Sub 明細書印刷範囲設定() + Dim ws As Worksheet + Dim lastRow As Long + Dim 合計Row As Long + Dim printStartRow As Long, printEndRow As Long + + Set ws = ThisWorkbook.Sheets("明細書") + + ' B列の最終行取得 + lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row + + ' B列の最終行から上方向に「合計」を探す + 合計Row = 0 + Dim i As Long + For i = lastRow To 2 Step -1 + If ws.Cells(i, "B").Value = "合計" Then + 合計Row = i + Exit For + End If + Next i + + If 合計Row = 0 Then + MsgBox "「合計」が見つかりません。", vbExclamation + Exit Sub + End If + + printStartRow = 2 + printEndRow = 合計Row + 3 + + ws.PageSetup.PrintArea = ws.Range("B" & printStartRow & ":F" & printEndRow).Address + 'MsgBox "印刷範囲をF" & printStartRow & "~F" & printEndRow & "に設定しました。", vbInformation + +End Sub + +Sub 入力内容をすべてクリア() + If MsgBox("基本情報および部材リストの選択をすべてクリアします、よろしいですか?", vbYesNo + vbQuestion, "確認") = vbNo Then + Exit Sub + End If + Call 基本入力のE列クリア + Call 複数シートF列クリア +End Sub + +Sub 複数シートF列クリア() + Dim sheetNames As Variant + Dim i As Integer + Dim ws As Worksheet + sheetNames = Array("NBサッシ工事", "NB内部建具", "NB設備", "B雑工事", "N雑工事", "Aサッシ工事", "A内部建具", "A設備", "A雑工事") + For i = LBound(sheetNames) To UBound(sheetNames) + On Error Resume Next + Set ws = ThisWorkbook.Sheets(sheetNames(i)) + If Not ws Is Nothing Then + ws.Range("F4:F10000").ClearContents + End If + Set ws = Nothing + On Error Goto 0 + Next i +End Sub + +Sub 基本入力のE列クリア() + Dim ws As Worksheet + Dim i As Long + Set ws = ThisWorkbook.Sheets("基本入力") + For i = 1 To 100 + If ws.Cells(i, "B").Value = 1 Then + ws.Cells(i, "E").ClearContents + End If + Next i +End Sub + +Sub ファイルを別名保存() + Dim folderPath As String + Dim koujiName As String + Dim dt As String + Dim saveFileName As String + + ' 保存先フォルダ(現在のブックと同じ場所) + folderPath = ThisWorkbook.Path & "\" + + ' 工事名取得 + koujiName = Range("工事名").Value + + ' 日時取得(yyyyMMdd-HHMMSS形式) + dt = Format(Now, "yyyymmdd-HHMMSS") + + ' ファイル名作成 + saveFileName = folderPath & "nBAH積算システム" & "■" & koujiName & "■" & dt & ".xlsm" + + ' 別名で保存 + ThisWorkbook.SaveAs Filename:=saveFileName, FileFormat:=xlOpenXMLWorkbookMacroEnabled + + MsgBox "ファイルを保存しました。" & vbCrLf & saveFileName, vbInformation +End Sub + +Sub シート保護と非表示処理() + Dim ws As Worksheet + Dim pwd As String + pwd = ThisWorkbook.Sheets("基本入力").Range("Z10000").Value + + Application.ScreenUpdating = False + + ' 全シートをパスワードで保護 + For Each ws In ThisWorkbook.Worksheets + ws.Protect Password:=pwd, UserInterfaceOnly:=True + Next ws + + ' 指定以外のシートを非表示 + For Each ws In ThisWorkbook.Worksheets + If ws.Name <> "見積書" And ws.Name <> "明細書" And ws.Name <> "基本入力" Then + ws.Visible = xlSheetHidden + Else + ws.Visible = xlSheetVisible + End If + Next ws + + Application.ScreenUpdating = True + ' 元のシートに戻る + Call 基本入力シートに戻る + ActiveSheet.Range("E4").Select + +End Sub + +Sub シート保護解除() + Dim ws As Worksheet + Dim pwd As String + pwd = ThisWorkbook.Sheets("基本入力").Range("Z10000").Value + + Application.ScreenUpdating = False + + ' 全シートの保護を解除 + For Each ws In ThisWorkbook.Worksheets + ws.Unprotect Password:=pwd + Next ws + + Application.ScreenUpdating = True + ' 元のシートに戻る + Call 基本入力シートに戻る + ActiveSheet.Range("E4").Select + +End Sub diff --git a/pleasanter/develop/##実行予算承認WF/connectionSetting/next999.json b/pleasanter/develop/##実行予算承認WF/connectionSetting/next999.json new file mode 100644 index 00000000..aeb831e2 --- /dev/null +++ b/pleasanter/develop/##実行予算承認WF/connectionSetting/next999.json @@ -0,0 +1,4 @@ +{ + "apiKey": "c38903157cbffc30961f50bc29d0991a6cd8af495ab3009b05c5f98e82b2e61b94ba2d5c0a48fc518b1cd74c9e427b01051a228f670f3c5282544dfbec93db87", + "url": "https://neo999.next-hd.net/pleasanter/" +} \ No newline at end of file diff --git a/pleasanter/develop/##実行予算承認WF/sites/scripts/01_メインスクリプト.js b/pleasanter/develop/##実行予算承認WF/sites/scripts/01_メインスクリプト.js new file mode 100644 index 00000000..a708d08a --- /dev/null +++ b/pleasanter/develop/##実行予算承認WF/sites/scripts/01_メインスクリプト.js @@ -0,0 +1,272 @@ +/* +@config : next999.json +@filename : ${psFileBasename} +@title : 01_メインスクリプト +@name : +@siteIds : 335011 +@siteTitles : 実行予算WF申請 +@disabled: false +*/ +let pageLoading = 0; +let apiKey = '6504c8a807677a3a576e10327f3c19876c55736ee45d4a845796b9e7f5e087bfd4bd0d8184863da8cf1733ca635111432ab334aea59102b06a96ee6d2c05190d'; + +let areaNotificationList = JSON.parse($('#areaNotificationList').val() || '{}'); +let classNotificationList = JSON.parse($('#classNotificationList').val() || '{}'); + +//---------------------------------------------------------------------- +//初期処理 +window.addEventListener('load', function () { + if (pageLoading == 0) { + console.log('Window load Event'); + $p.ex.onLoad(); + } +}); + +$p.events.on_editor_load = function () { + if (pageLoading == 0) { + console.log('on Editor Load'); + $p.ex.onLoad(); + } +} + +$p.ex.onLoad = function () { + //ロード開始 + pageLoading = 1; + + //初期処理 + $p.ex.init(); +} + +//---------------------------------------------------------------------- +$p.ex.init = function () { + console.log('initialize...'); + //初期化 + + //初期表示 + const classX = $('input[name="Results_ClassX"]:checked').val(); + $p.ex.changeMode(classX); + + console.log('initialize...done'); + +} + +//ClassXの選択値を取得 +$('input[name="Results_ClassX"]:radio').change(function () { + const selectedValue = $(this).val(); + console.log('Results_ClassX changed:', selectedValue); + // 必要な処理をここに追加 + $p.ex.changeMode(selectedValue); +}); + +$p.events.before_validate_Create = function (args) { + //新規作成時の処理 + console.log('New Create...'); + $p.ex.setUsers(); +} + +//保存前処理 +$p.events.before_validate = function (args) { + console.log('Before Validate...'); + + const classX = $('input[name="Results_ClassX"]:checked').val(); + switch (classX) { + case '1': + $p.set($('#Results_ClassY'), $('#Results_Date001').val()); + $p.set($('#Results_Date002'), ''); + $p.set($('#Results_Date003'), ''); + $p.set($('#Results_Date004'), ''); + $p.set($('#Results_Date005'), ''); + $p.set($('#Results_Num001'), ''); + break; + case '2': + $p.set($('#Results_ClassY'), $('#Results_Date002').val()); + $p.set($('#Results_Date001'), ''); + $p.set($('#Results_Date003'), ''); + $p.set($('#Results_Date004'), ''); + $p.set($('#Results_Date005'), ''); + $p.set($('#Results_Num001'), ''); + break; + case '3': + $p.set($('#Results_ClassY'), $('#Results_Date003').val()); + $p.set($('#Results_Date001'), ''); + $p.set($('#Results_Date002'), ''); + $p.set($('#Results_Date004'), ''); + $p.set($('#Results_Date005'), ''); + $p.set($('#Results_Num001'), ''); + break; + case '4': + $p.set($('#Results_ClassY'), $('#Results_Date004').val()); + $p.set($('#Results_Date001'), ''); + $p.set($('#Results_Date002'), ''); + $p.set($('#Results_Date003'), ''); + $p.set($('#Results_Date005'), ''); + $p.set($('#Results_Num001'), ''); + break; + case '5': + $p.set($('#Results_ClassY'), $('#Results_Date005').val()); + $p.set($('#Results_Date001'), ''); + $p.set($('#Results_Date002'), ''); + $p.set($('#Results_Date003'), ''); + $p.set($('#Results_Date004'), ''); + $p.set($('#Results_Num001'), ''); + break; + case '6': + $p.set($('#Results_ClassY'), $('#Results_Num001').val() + ' 回'); + $p.set($('#Results_Date001'), ''); + $p.set($('#Results_Date002'), ''); + $p.set($('#Results_Date003'), ''); + $p.set($('#Results_Date004'), ''); + $p.set($('#Results_Date005'), ''); + break; + default: + } + + +} + +//保存後処理 +$p.events.after_set = function (args) { + //初期処理 + $p.ex.init(); +} + +//マスターシートからデータを取得 +$p.on('change', 'ClassA', function () { + $p.ex.getMSSData(); +}); + +//マスターシートの情報取得 +$p.ex.getMSSData = function () { + let resultId = $("#Results_ClassA").val(); + + $p.apiGet({ + 'id': resultId, + 'done': function (data) { + console.log(data); + if (data.Response.TotalCount == '1') { + let mssData = data.Response.Data[0]; + + console.log('MSSデータをセット'); + // 工事名の末尾に「様」または空白があれば削除 + let classQ = mssData.ClassHash.ClassQ || ''; + classQ = classQ.replace(/[\s様]+$/, ''); + if (classQ !== '') { + classQ = classQ + ' 様邸'; + } + $p.set($('#Results_ClassB'), classQ); //工事名 + $p.set($('#Results_ClassC'), mssData.ClassHash.ClassA); //契約コード + + $p.set($('#Results_ClassI'), mssData.ClassHash.Class033); //契約ブランド + $p.set($('#Results_ClassJ'), mssData.ClassHash.Class043); //建物種類 + + //延床面積選択 + let num016 = parseFloat(mssData.NumHash.Num016 || '0'); + if (num016 < 21) { + $p.set($('#Results_ClassK'), '~20坪'); //延床面積 + } else if (num016 < 31) { + $p.set($('#Results_ClassK'), '21~30坪'); //延床面積 + } else if (num016 < 41) { + $p.set($('#Results_ClassK'), '31~40坪'); //延床面積 + } else if (num016 < 51) { + $p.set($('#Results_ClassK'), '41~50坪'); //延床面積 + } else { + $p.set($('#Results_ClassK'), '51坪~'); //延床面積 + } + + $p.set($('#Results_ClassL'), mssData.ClassHash.Class036); //構造材 + + //承認図予定日 + if (mssData.DateHash.DateH != '1899-12-30T00:00:00') { + let dateH = new Date(mssData.DateHash.DateH); + let dateHStr = dateH.getFullYear() + '/' + (dateH.getMonth() + 1).toString().padStart(2, '0') + '/' + dateH.getDate().toString().padStart(2, '0'); + $p.set($('#Results_DateB'), dateHStr); + } + + //着工予定日 + if (mssData.DateHash.Date063 != '1899-12-30T00:00:00') { + let date063 = new Date(mssData.DateHash.Date063); + let date063Str = date063.getFullYear() + '/' + (date063.getMonth() + 1).toString().padStart(2, '0') + '/' + date063.getDate().toString().padStart(2, '0'); + $p.set($('#Results_DateC'), date063Str); + } + + $p.clearMessage(); + $p.ex.setMyMessage('new-status-lime', 'マスターシートの情報を取得しました'); + + } else { + //既存データクリア + $p.clearMessage(); + $p.ex.setMyMessage('new-status-red', 'マスターシートの情報を取得に失敗しました'); + + } + }, + 'fail': function (data) { + console.log(data); + //既存データクリア + $p.clearMessage(); + $p.ex.setMyMessage('new-status-red', 'マスターシートの情報を取得に失敗しました'); + + } + }); +} + +$p.ex.setUsers = function () { + console.log(areaNotificationList); + console.log(classNotificationList); + //担当監督マスタ、通知先マスタの情報を元に、担当監督、通知先をセットする + let area = $('#Results_ClassD').val() || ''; + let mode = $('#Results_ClassX').val() || ''; + + if (area != '' && mode != '') { + $p.set($('#Results_Class001'), areaNotificationList[area].list1); + $p.set($('#Results_Class002'), areaNotificationList[area].list2); + $p.set($('#Results_Class003'), areaNotificationList[area].list3); + $p.set($('#Results_Class004'), areaNotificationList[area].list4); + + $p.set($('#Results_Class005'), classNotificationList[mode].list1); + $p.set($('#Results_Class006'), classNotificationList[mode].list2); + //最終承認者 + $p.set($('#Results_Class010'), classNotificationList[mode].list3); + + console.log('担当監督、通知先をセットしました'); + } else { + console.log('担当監督、通知先のセットに失敗しました'); + } + +} + + +$p.ex.changeMode = function (mode) { + // + $('#Results_Date001Field').hide(); + $('#Results_Date002Field').hide(); + $('#Results_Date003Field').hide(); + $('#Results_Date004Field').hide(); + $('#Results_Date005Field').hide(); + $('#Results_Num001Field').hide(); + console.log('changeMode...'); + + // モード変更に伴う処理をここに追加 + //const classX = $('#Results_ClassX').val(); + switch (mode) { + case '1': + $('#Results_Date001Field').show(); + break; + case '2': + $('#Results_Date002Field').show(); + break; + case '3': + $('#Results_Date003Field').show(); + break; + case '4': + $('#Results_Date004Field').show(); + break; + case '5': + $('#Results_Date005Field').show(); + break; + case '6': + $('#Results_Num001Field').show(); + break; + default: + } +} + diff --git a/pleasanter/develop/##実行予算承認WF/sites/scripts/99.参照用.js b/pleasanter/develop/##実行予算承認WF/sites/scripts/99.参照用.js new file mode 100644 index 00000000..b6432e9e --- /dev/null +++ b/pleasanter/develop/##実行予算承認WF/sites/scripts/99.参照用.js @@ -0,0 +1,37 @@ + +[ + { + "TableName": "Users", + "View": { + "ColumnFilterExpressions": { + "UserId": "[@Class001]" + } + } + } +] + + +[ + { + "TableName": "Users", + "View": { + "ColumnFilterExpressions": { + "UserId": "[@Class010]" + } + } + } +] + +[ + { + "TableName": "Users", + "View": { + "ColumnFilterHash": { + "DeptId": "26", + }, + "ColumnSorterHash": { + "UserId": "asc" + } + } + } +] \ No newline at end of file diff --git a/pleasanter/develop/##実行予算承認WF/sites/scripts/抽出マクロ.vbs b/pleasanter/develop/##実行予算承認WF/sites/scripts/抽出マクロ.vbs new file mode 100644 index 00000000..8397a468 --- /dev/null +++ b/pleasanter/develop/##実行予算承認WF/sites/scripts/抽出マクロ.vbs @@ -0,0 +1,327 @@ +Option Explicit + +Sub 明細の抽出() + If Range("選択ブランド").Value = "" Then + MsgBox "ブランドが選択されていません。", vbExclamation + Exit Sub + End If + + Application.ScreenUpdating = False + + Call 抽出シートクリア("抽出") + Call 明細情報抽出("サッシ工事", "抽出") + Call 明細情報抽出("内部建具工事", "抽出") + Call 明細情報抽出("設備工事", "抽出") + Call 明細情報抽出("雑工事", "抽出") + + Call 明細書シートに移動() + Call 明細書印刷範囲設定() + + Application.ScreenUpdating = True +End Sub + + +' filepath: c:\Users\k.nogi\#GitHub\ken_nogi\pleasanter\develop\##実行予算承認WF\sites\scripts\抽出マクロ.vbs +Sub 明細情報抽出(Byval categoryName As String, Byval destSheetName As String) + Dim srcWs As Worksheet, destWs As Worksheet + Dim srcTbl As ListObject + Dim destRow As Long, i As Long + Dim colProduct As Integer, colPrice As Integer, colQty As Integer, colUnit As Integer, colUnitName As Integer + Dim 金額 As Double, subtotal As Double + Dim lastRow As Long + Dim isFirst As Boolean + + '--- 対象のテーブル情報 --- + Dim srcSheetName As String + Dim srcTableName As String + srcSheetName = Range(categoryName).Value + srcTableName = Range(categoryName).Value + + '--- 設定 --- + Set srcWs = ThisWorkbook.Sheets(srcSheetName) + Set destWs = ThisWorkbook.Sheets(destSheetName) + Set srcTbl = srcWs.ListObjects(srcTableName) + + '列番号取得(列名は実際のものに合わせてください) + colProduct = srcTbl.ListColumns("商品名").Index + colPrice = srcTbl.ListColumns("単価").Index + colUnit = srcTbl.ListColumns("単位").Index + colQty = srcTbl.ListColumns("数量").Index + colUnitName = srcTbl.ListColumns("単位名").Index + + '--- データ書き込み開始行の決定 --- + lastRow = destWs.Cells(destWs.Rows.Count, 1).End(xlUp).Row + If destWs.Cells(1, 1).Value = "" Then + ' シートが空の場合 + destRow = 1 + isFirst = True + Else + destRow = lastRow + 1 + isFirst = False + End If + + '--- カテゴリ名・ヘッダー出力 --- + destWs.Cells(destRow, 1).Value = categoryName + destRow = destRow + 1 + + subtotal = 0 + + '--- データ抽出と金額計算 --- + For i = 1 To srcTbl.ListRows.Count + If srcTbl.DataBodyRange(i, colQty).Value > 0 Then + destWs.Cells(destRow, 1).Value = " " + srcTbl.DataBodyRange(i, colProduct).Value + destWs.Cells(destRow, 2).Value = srcTbl.DataBodyRange(i, colPrice).Value + destWs.Cells(destRow, 3).Value = srcTbl.DataBodyRange(i, colUnit).Value + destWs.Cells(destRow, 4).Value = srcTbl.DataBodyRange(i, colQty).Value + destWs.Cells(destRow, 5).Value = srcTbl.DataBodyRange(i, colUnitName).Value + 金額 = srcTbl.DataBodyRange(i, colPrice).Value * srcTbl.DataBodyRange(i, colUnit).Value * srcTbl.DataBodyRange(i, colQty).Value + destWs.Cells(destRow, 6).Value = 金額 + subtotal = subtotal + 金額 + destRow = destRow + 1 + End If + Next + + '--- 小計行(商品名と同じ列に"小計") --- + destWs.Cells(destRow, 1).Value = " 小計" + destWs.Cells(destRow, 6).Value = subtotal + + 'MsgBox "抽出と金額計算が完了しました", vbInformation +End Sub + + +Sub 抽出シートクリア(Byval destSheetName As String) + Dim destWs As Worksheet + Set destWs = ThisWorkbook.Sheets(destSheetName) + destWs.Cells.ClearContents +End Sub + +Sub シートの切り替え() + Application.ScreenUpdating = False + '全シート非表示 + Call 全シート非表示 + + '必要なシートのみ表示 + Call 指定シート表示("サッシ工事") + Call 指定シート表示("内部建具工事") + Call 指定シート表示("設備工事") + Call 指定シート表示("雑工事") + + Application.ScreenUpdating = True +End Sub + +Sub 全シート非表示() + Dim sheetNames As Variant + Dim i As Integer + sheetNames = Array("NBサッシ工事", "NB内部建具", "NB設備", "B雑工事", "N雑工事", "Aサッシ工事", "A内部建具", "A設備", "A雑工事") + For i = LBound(sheetNames) To UBound(sheetNames) + On Error Resume Next + ThisWorkbook.Sheets(sheetNames(i)).Visible = xlSheetHidden + On Error Goto 0 + Next i +End Sub + +Sub 指定シート表示(Byval shName As String) + Dim sh As String + sh = Range(shName).Value + Dim ws As Worksheet + Set ws = ThisWorkbook.Sheets(sh) + ws.Visible = xlSheetVisible +End Sub + +Sub 基本入力シートに戻る() + Dim ws As Worksheet + Set ws = ThisWorkbook.Sheets("基本入力") + ws.Activate + ws.Range("A1").Select +End Sub + +Sub 見積書シートに移動() + Dim ws As Worksheet + Set ws = ThisWorkbook.Sheets("見積書") + ws.Activate + ws.Range("A1").Select +End Sub + +Sub 明細書シートに移動() + Dim ws As Worksheet + Set ws = ThisWorkbook.Sheets("明細書") + ws.Activate + ws.Range("A1").Select +End Sub + +Sub セル参照でシート移動(Byval sheetName As String) + Dim ws As Worksheet + Set ws = ThisWorkbook.Sheets(sheetName) + If ws.Visible = xlSheetHidden Or ws.Visible = xlSheetVeryHidden Then + Call シートの切り替え + End If + ws.Activate + ws.Range("F4").Select +End Sub + +Sub サッシ工事テーブルへ移動() + If Range("選択ブランド").Value = "" Then + MsgBox "ブランドが選択されていません。", vbExclamation + Exit Sub + End If + Call セル参照でシート移動(Range("サッシ工事").Value) +End Sub + +Sub 内部建具工事テーブルへ移動() + If Range("選択ブランド").Value = "" Then + MsgBox "ブランドが選択されていません。", vbExclamation + Exit Sub + End If + Call セル参照でシート移動(Range("内部建具工事").Value) +End Sub + +Sub 設備工事テーブルへ移動() + If Range("選択ブランド").Value = "" Then + MsgBox "ブランドが選択されていません。", vbExclamation + Exit Sub + End If + Call セル参照でシート移動(Range("設備工事").Value) +End Sub + +Sub 雑工事テーブルへ移動() + If Range("選択ブランド").Value = "" Then + MsgBox "ブランドが選択されていません。", vbExclamation + Exit Sub + End If + Call セル参照でシート移動(Range("雑工事").Value) +End Sub + +Sub クリア() + ActiveSheet.Range("F4:F10000").ClearContents +End Sub + + +Sub 見積書明細書PDF出力() + Dim wsMitsumori As Worksheet, wsMeisai As Worksheet + Dim pdfFileName As String + Dim folderPath As String + Dim mitsumoriNo As String, koujiName As String, issueDate As String + + Set wsMitsumori = ThisWorkbook.Sheets("見積書") + Set wsMeisai = ThisWorkbook.Sheets("明細書") + + ' 保存先フォルダ(必要に応じて変更) + folderPath = ThisWorkbook.Path & "\" + + ' ファイル名用情報取得 + mitsumoriNo = Range("見積書番号").Value + koujiName = Range("工事名").Value + issueDate = Range("発行年月日").Value + + ' 日付を"yyyyMMddHHmmss"形式に + Dim dt As String + dt = Format(issueDate, "yyyymmdd-HHMMSS") + + ' ファイル名作成 + pdfFileName = folderPath & mitsumoriNo & "■" & koujiName & "■" & dt & ".pdf" + + ' シートを配列で指定してPDF出力 + Sheets(Array("見積書", "明細書")).Select + ActiveSheet.ExportAsFixedFormat Type:=xlTypePDF, Filename:=pdfFileName, Quality:=xlQualityStandard + + ' 元のシートに戻る + Call 基本入力シートに戻る() + + MsgBox "PDF出力が完了しました。" & vbCrLf & pdfFileName, vbInformation +End Sub + +Sub 明細書印刷範囲設定() + Dim ws As Worksheet + Dim lastRow As Long + Dim 合計Row As Long + Dim printStartRow As Long, printEndRow As Long + + Set ws = ThisWorkbook.Sheets("明細書") + + ' B列の最終行取得 + lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row + + ' B2から下方向に「合計」を探す + 合計Row = 0 + Dim i As Long + For i = 2 To lastRow + If IsError(ws.Cells(i, "B").Value) Or ws.Cells(i, "B").Value = CVErr(xlErrNA) Then + Continue For + End If + If ws.Cells(i, "B").Value = "合計" Then + 合計Row = i + Exit For + End If + Next i + + If 合計Row = 0 Then + MsgBox "「合計」が見つかりません。", vbExclamation + Exit Sub + End If + + printStartRow = 2 + printEndRow = 合計Row + 3 + + ws.PageSetup.PrintArea = ws.Range("B" & printStartRow & ":F" & printEndRow).Address + 'MsgBox "印刷範囲をF" & printStartRow & "~F" & printEndRow & "に設定しました。", vbInformation + +End Sub + +Sub 入力内容をすべてクリア() + If MsgBox("基本情報および部材リストの選択をすべてクリアします、よろしいですか?", vbYesNo + vbQuestion, "確認") = vbNo Then + Exit Sub + End If + Call 基本入力のE列クリア() + Call 複数シートF列クリア() +End Sub + +Sub 複数シートF列クリア() + Dim sheetNames As Variant + Dim i As Integer + Dim ws As Worksheet + sheetNames = Array("NBサッシ工事", "NB内部建具", "NB設備", "B雑工事", "N雑工事", "Aサッシ工事", "A内部建具", "A設備", "A雑工事") + For i = LBound(sheetNames) To UBound(sheetNames) + On Error Resume Next + Set ws = ThisWorkbook.Sheets(sheetNames(i)) + If Not ws Is Nothing Then + ws.Range("F4:F10000").ClearContents + End If + Set ws = Nothing + On Error Goto 0 + Next i +End Sub + +Sub 基本入力のE列クリア() + Dim ws As Worksheet + Dim i As Long + Set ws = ThisWorkbook.Sheets("基本入力") + For i = 1 To 100 + If ws.Cells(i, "B").Value = 1 Then + ws.Cells(i, "E").ClearContents + End If + Next i +End Sub + +Sub ファイルを別名保存() + Dim folderPath As String + Dim koujiName As String + Dim dt As String + Dim saveFileName As String + + ' 保存先フォルダ(現在のブックと同じ場所) + folderPath = ThisWorkbook.Path & "\" + + ' 工事名取得 + koujiName = Range("工事名").Value + + ' 日時取得(yyyyMMdd-HHMMSS形式) + dt = Format(Now, "yyyymmdd-HHMMSS") + + ' ファイル名作成 + saveFileName = folderPath & "nBAH積算システム" & "■" & koujiName & "■" & dt & ".xlsm" + + ' 別名で保存 + ThisWorkbook.SaveAs Filename:=saveFileName, FileFormat:=xlOpenXMLWorkbookMacroEnabled + + MsgBox "ファイルを保存しました。" & vbCrLf & saveFileName, vbInformation +End Sub \ No newline at end of file diff --git a/pleasanter/develop/##実行予算承認WF/sites/serverscripts/01_マスタデータ取得.js b/pleasanter/develop/##実行予算承認WF/sites/serverscripts/01_マスタデータ取得.js new file mode 100644 index 00000000..4a486f41 --- /dev/null +++ b/pleasanter/develop/##実行予算承認WF/sites/serverscripts/01_マスタデータ取得.js @@ -0,0 +1,114 @@ +/* +@config :next999.json +@filename : ${psFileBasename} +@title :01_マスタデータ取得 +@name :01_マスタデータ取得 +@siteIds : 335011 +@siteTitles : 実行予算WF申請 +@disabled: false +*/ + +try { + //マスタデータ取得 + getMasterData1(); + getMasterData2(); + +} catch (error) { + context.Log(error); + +} + +//マスタデータ取得1 +function getMasterData1() { + //担当監督マスタ + let masterTableId = '335031'; + let data = { + "View": { + "ColumnSorterHash": { + "NumA": "asc" + } + } + } + + let results = items.Get(masterTableId, JSON.stringify(data)); + if (results.Length === 0) { + context.Log('担当監督マスタデータが見つかりませんでした。1'); + return; + } + + let areaNotificationList = {}; + let count = 0; + for (let item of results) { + const area = item.ClassA; + const list1 = item.ClassB; + const list2 = item.ClassC; + const list3 = item.ClassD; + const list4 = item.ClassE; + + areaNotificationList[area] = { + "list1": list1, + "list2": list2, + "list3": list3, + "list4": list4 + }; + + count++; + } + + //取得したデータをhiddenに格納 + if (count > 0) { + hidden.Add('areaNotificationList', JSON.stringify(areaNotificationList)); + context.Log('担当監督マスタデータ取得完了'); + return; + } else { + context.Log('担当監督マスタデータが見つかりませんでした。2'); + return; + } + +} + +//マスタデータ取得2 +function getMasterData2() { + //通知先マスタ + let masterTableId = '335032'; + let data = { + "View": { + "ColumnSorterHash": { + "NumA": "asc" + } + } + } + + let results = items.Get(masterTableId, JSON.stringify(data)); + if (results.Length === 0) { + context.Log('通知先マスタデータが見つかりませんでした。3'); + return; + } + + let classNotificationList = {}; + let count = 0; + for (let item of results) { + const shubetu = item.ClassA; + const list1 = item.ClassB; + const list2 = item.ClassC; + const list3 = item.ClassD; + + classNotificationList[shubetu] = { + "list1": list1, + "list2": list2, + "list3": list3 + }; + + count++; + } + + //取得したデータをhiddenに格納 + if (count > 0) { + hidden.Add('classNotificationList', JSON.stringify(classNotificationList)); + context.Log('通知先マスタデータ取得完了'); + return; + } else { + context.Log('通知先マスタデータが見つかりませんでした。4'); + return; + } +} \ No newline at end of file diff --git a/pleasanter/develop/##実行予算承認WF/sites/styles/01_基本スタイル設定.css b/pleasanter/develop/##実行予算承認WF/sites/styles/01_基本スタイル設定.css new file mode 100644 index 00000000..0dc69858 --- /dev/null +++ b/pleasanter/develop/##実行予算承認WF/sites/styles/01_基本スタイル設定.css @@ -0,0 +1,30 @@ +/* +@config : next999.json +@filename : ${psFileBasename} +@title : 01_基本スタイル設定 +@name : +@siteIds : 335011 +@siteTitles : 実行予算WF申請 +@disabled: false +*/ +/*見出しサイズ*/ +.field-section { + font-size: 1.5em !important; + font-weight: bold !important; + height: auto; +} + +/*項目の後ろの行間を少し狭める*/ +.field-normal { + height: 35px; +} + +.field-wide { + min-height: 35px; + padding: 0 10px 5px 0; +} + +/*コメントのある項目の高さだけ少し広げる*/ +div:has(.commentAdd).field-normal { + height: 50px; +} \ No newline at end of file diff --git a/pleasanter/develop/##実行予算承認WF/sites/styles/02_個別スタイル調整.css b/pleasanter/develop/##実行予算承認WF/sites/styles/02_個別スタイル調整.css new file mode 100644 index 00000000..4c5cd865 --- /dev/null +++ b/pleasanter/develop/##実行予算承認WF/sites/styles/02_個別スタイル調整.css @@ -0,0 +1,28 @@ +/* +@config : next999.json +@filename : ${psFileBasename} +@title : 02_個別スタイル調整 +@name : +@siteIds : 335011 +@siteTitles : 実行予算WF申請 +@disabled: false +*/ + +#Results_ClassXField { + font-size: 1.5em !important; + + & label { + font-weight: bold !important; + } + + & input[type="radio"] { + accent-color: #f00; + transform: scale(1.5); + margin-top: 8px; + margin-left: 10px; + } +} + +label[for="Results_ClassX"] { + color: #f00 !important; +} \ No newline at end of file diff --git a/pleasanter/develop/##実行予算承認WF/sites/styles/99_読み取り専用処理.css b/pleasanter/develop/##実行予算承認WF/sites/styles/99_読み取り専用処理.css new file mode 100644 index 00000000..a3e966e6 --- /dev/null +++ b/pleasanter/develop/##実行予算承認WF/sites/styles/99_読み取り専用処理.css @@ -0,0 +1,109 @@ +/* +@config : next999.json +@filename : ${psFileBasename} +@title : 99_読み取り専用処理 +@name +@siteIds : 335011 +@siteTitles : 実行予算WF申請 +@disabled: false +*/ +label.error { + pointer-events: none; + z-index: 100; + border-top: none !important; +} + +.code-readonly { + pointer-events: none; + background-color: lightgrey; + font-weight: bold; +} + +.code-readonly2, +.code-readonly2+button, +.code-readonly2+div.ui-icon, +.code-readonly3, +.code-readonly3+button, +.code-readonly3+div.ui-icon { + font-weight: bold; + + &:active { + pointer-events: none; + } + + a:not(.ui-spinner-button) { + pointer-events: auto; + } + +} + +.code-readonly2 select, +.code-readonly2 input, +.code-readonly2 button.ui-multiselect, +.code-readonly2 .control-markup, +.code-readonly2 .ui-spinner, +span[data-readonly="1"] { + pointer-events: none; + + border: dashed 1px black !important; + background-color: lightgray !important; + color: black !important; + + .ui-spinner-input { + border: none; + } +} + +.code-readonly3 select, +.code-readonly3 input, +.code-readonly3 button.ui-multiselect, +.code-readonly3 .control-markup, +.code-readonly3 .ui-spinner { + pointer-events: none; + + border: dashed 1px black !important; + + .ui-spinner-input { + border: none; + } +} + +.code-readonly2, +.code-readonly3, +.field-normal:has(span[data-readonly="1"]), +.field-wide:has(span[data-readonly="1"]) { + position: relative; + + &:hover::after { + content: "読取り専用です"; + position: absolute; + left: 120px; + top: calc(100% - 9px); + margin-top: 4px; + background: #00000080; + color: #fff; + padding: 4px 10px; + border-radius: 4px; + font-size: 12px; + font-weight: normal !important; + pointer-events: none; + z-index: 9999; + white-space: nowrap; + } +} + +.code-required, +select[data-validate-required="1"], +input[data-validate-required="1"] { + border: solid 2px red !important; + + &+button.ui-multiselect { + border: solid 2px red !important; + } + +} + +label[class="required"] { + color: red !important; + font-weight: bold !important; +} \ No newline at end of file diff --git a/pleasanter/develop/#営業積算/doc/プリザンター定義書■営業積算Re①基本情報.xlsx b/pleasanter/develop/#営業積算/doc/プリザンター定義書■営業積算Re①基本情報.xlsx index 76de64cc..aa17433b 100644 Binary files a/pleasanter/develop/#営業積算/doc/プリザンター定義書■営業積算Re①基本情報.xlsx and b/pleasanter/develop/#営業積算/doc/プリザンター定義書■営業積算Re①基本情報.xlsx differ diff --git a/pleasanter/develop/#営業積算/doc/営業積算_リニューアル2024-selected/★積算問い合わせ2025ver_プリザンター項目定義書.xlsx b/pleasanter/develop/#営業積算/doc/営業積算_リニューアル2024-selected/★積算問い合わせ2025ver_プリザンター項目定義書.xlsx index 5d7132ff..83172e54 100644 Binary files a/pleasanter/develop/#営業積算/doc/営業積算_リニューアル2024-selected/★積算問い合わせ2025ver_プリザンター項目定義書.xlsx and b/pleasanter/develop/#営業積算/doc/営業積算_リニューアル2024-selected/★積算問い合わせ2025ver_プリザンター項目定義書.xlsx differ diff --git a/pleasanter/develop/#営業積算v3/■1_335018_Re①基本情報/sites/scripts/02_MSSデータ処理.js b/pleasanter/develop/#営業積算v3/■1_335018_Re①基本情報/sites/scripts/02_MSSデータ処理.js index 0598566f..ada96c0b 100644 --- a/pleasanter/develop/#営業積算v3/■1_335018_Re①基本情報/sites/scripts/02_MSSデータ処理.js +++ b/pleasanter/develop/#営業積算v3/■1_335018_Re①基本情報/sites/scripts/02_MSSデータ処理.js @@ -8,6 +8,75 @@ @disabled: false */ +$p.ex.getMSSData = function () { + let resultId = $("#Results_ClassY").val(); + + $p.apiGet({ + 'id': resultId, + 'done': function (data) { + console.log(data); + if (data.Response.TotalCount == '1') { + let mssData = data.Response.Data[0]; + + //既存データクリア + console.log('Clear MSS Data before Set'); + $p.ex.clearMSSData(); + + console.log('Set MSS Data'); + $p.set($('#Results_ClassZ'), mssData.ClassHash.ClassA); //契約コード + $p.set($('#Results_Class001'), mssData.ClassHash.Class001); //施主・姓 + $p.set($('#Results_Class002'), mssData.ClassHash.Class002); //施主・名 + $p.set($('#Results_Class003'), mssData.ClassHash.Class003); //施主・姓(カナ) + $p.set($('#Results_Class004'), mssData.ClassHash.Class004); //施主・名(カナ) + $p.set($('#Results_Class005'), mssData.ClassHash.ClassQ); //工事名 + $p.set($('#Results_Class006'), mssData.ClassHash.ClassR); //工事名_カナ + $p.set($('#Results_Class010'), mssData.ClassHash.Class029); //建上地 + $p.set($('#Results_Class011'), mssData.ClassHash.ClassW); //エリア + $p.set($('#Results_Class012'), mssData.ClassHash.Class033); //契約ブランド + $p.set($('#Results_Class013'), mssData.ClassHash.Class040); //防火指定 + $p.set($('#Results_Class014'), mssData.ClassHash.Class043); //建物種類 + + $p.set($('#Results_Class021'), mssData.ClassHash.ClassF); //契約営業所 + $p.set($('#Results_Class022'), mssData.ClassHash.ClassG); //主担当営業 + $p.set($('#Results_Class023'), mssData.ClassHash.ClassH); //副担当営業 + $p.set($('#Results_Class024'), mssData.ClassHash.ClassI); //営業設計 + $p.set($('#Results_Class025'), mssData.ClassHash.ClassJ); //担当監督 + $p.set($('#Results_Class026'), mssData.ClassHash.ClassK); //担当IC + $p.set($('#Results_Class027'), mssData.ClassHash.ClassL); //管理設計 + $p.set($('#Results_Class028'), mssData.ClassHash.ClassY); //所属長 + + if (mssData.DateHash.DateH != '1899-12-30T00:00:00') { + let dateH = new Date(mssData.DateHash.DateH); + let dateHStr = dateH.getFullYear() + '/' + (dateH.getMonth() + 1).toString().padStart(2, '0') + '/' + dateH.getDate().toString().padStart(2, '0'); + $p.set($('#Results_Date001'), dateHStr); + } + + if (mssData.DateHash.Date063 != '1899-12-30T00:00:00') { + let date063 = new Date(mssData.DateHash.Date063); + let date063Str = date063.getFullYear() + '/' + (date063.getMonth() + 1).toString().padStart(2, '0') + '/' + date063.getDate().toString().padStart(2, '0'); + $p.set($('#Results_Date002'), date063Str); + } + + $p.set($('#Results_ClassS'), '1'); //案件状況 + + $p.clearMessage(); + $p.ex.setMyMessage('new-status-lime', 'マスターシートの情報を取得しました'); + + + } else { + //既存データクリア + $p.ex.clearMSSData(); + + } + }, + 'fail': function (data) { + console.log(data); + //既存データクリア + $p.ex.clearMSSData(); + + } + }); +} //MSSからの引用データをクリア $p.ex.clearMSSData = function () {