자바스크립트로 견적금액 소계, 합계 만들어보자구요~
몇시간째 고생해서.. 만든코드입니다.
소계,합계
산출내역서... 가지고 만들어봅니다.
function inputNumber(input) {
// 현재 커서 위치를 저장
const cursorPosition = input.selectionStart;
// 입력값에서 숫자만 남기고 제거
const value = input.value.replace(/,/g, '');
// 천 단위 콤마 추가
const formattedValue = Number(value).toLocaleString();
// 포맷팅된 값으로 설정
input.value = formattedValue;
// 포맷팅 후에도 원래 커서 위치 유지
input.setSelectionRange(cursorPosition, cursorPosition);
}
// 숫자 포맷팅 함수 (콤마 추가)
function formatNumber(value) {
return new Intl.NumberFormat().format(value);
}
// 숫자에서 콤마를 제거하는 함수
function cleanNumber(value) {
return parseFloat(value.replace(/,/g, '')) || 0;
}
function calculateRowTotal(row) {
const suInput = row.querySelector('.su-input');
const areaLengthInput = row.querySelector('.area-length-input');
const areaPriceInput = row.querySelector('.area-price-input');
const unitPriceInput = row.querySelector('.unit-price-input');
// 요소가 존재하는지 확인 후 값 읽기
const su = suInput ? cleanNumber(suInput.value) : 1;
const areaLength = areaLengthInput ? cleanNumber(areaLengthInput.value) : 1; // 없으면 1로 처리
const areaPrice = areaPriceInput ? cleanNumber(areaPriceInput.value) : 1;
let unitPrice = unitPriceInput ? cleanNumber(unitPriceInput.value) : 1;
let totalPrice = 0;
// areaPrice 소수점 둘째 자리까지 반올림
const roundedAreaPrice = parseFloat(areaPrice.toFixed(2));
// 콘솔에 현재 값을 출력해보기
console.log('수량(su):', su);
console.log('면적 길이(areaLength):', areaLength);
console.log('면적 단가(roundedAreaPrice):', roundedAreaPrice);
console.log('단가(unitPrice):', unitPrice);
if (roundedAreaPrice) {
unitPrice = areaLength * roundedAreaPrice; // 기본 수량 * 단가
totalPrice = Math.ceil(su * parseFloat(unitPrice.toFixed(0))); // 기본 수량 * 단가
console.log('계산된 단가 (unitPrice):', unitPrice);
console.log('계산된 총합(totalPrice):', totalPrice);
}
else if (areaLength) {
totalPrice = Math.ceil( su * areaLength * parseFloat(unitPrice.toFixed(0)) ) ; // 기본 수량 * 단가
console.log('계산된 총합(totalPrice) (면적이 있을 경우):', totalPrice);
}
else {
totalPrice = Math.ceil(su * parseFloat(unitPrice.toFixed(0)) ); // 기본 수량 * 단가
console.log('계산된 총합(totalPrice) (면적이 없을 경우):', totalPrice);
}
// 총 합계를 표시
const totalCell = row.querySelector('.total-price');
if (totalCell) {
totalCell.textContent = formatNumber(totalPrice);
}
return Math.ceil(totalPrice);
}
function calculateSubtotalBySerial(serialNumber) {
let subtotal = 0;
// 해당 일련번호에 해당하는 행들만 선택
const rows = document.querySelectorAll(`.calculation-row[data-serial="${serialNumber}"]`);
rows.forEach(row => {
subtotal += calculateRowTotal(row); // 각 행의 총 합계 계산
});
// 해당 일련번호의 소계 셀 업데이트
const subtotalCell = document.querySelector(`.subtotal-cell[data-serial="${serialNumber}"]`);
if (subtotalCell) {
subtotalCell.textContent = formatNumber(subtotal);
} else {
console.error(`소계 셀을 찾을 수 없습니다. 일련번호: ${serialNumber}`);
}
return subtotal;
}
function calculateAllSubtotals() {
let grandTotal = 0;
// 모든 일련번호에 대한 소계를 계산
const uniqueSerials = new Set();
document.querySelectorAll('.calculation-row').forEach(row => {
uniqueSerials.add(row.dataset.serial); // 중복되지 않는 일련번호 수집
});
uniqueSerials.forEach(serialNumber => {
grandTotal += calculateSubtotalBySerial(serialNumber); // 각 일련번호의 소계를 계산
});
return grandTotal;
}
function calculateGrandTotal() {
const grandTotal = calculateAllSubtotals();
const grandTotalCell = document.querySelector('.grand-total'); // 전체 합계 셀 클래스 접근
if (grandTotalCell) {
grandTotalCell.textContent = formatNumber(grandTotal);
} else {
console.error("전체 합계 셀을 찾을 수 없습니다. '.grand-total'이라는 클래스가 올바르게 설정되었는지 확인해주세요.");
}
}
// 이벤트 리스너 설정
document.querySelectorAll('input').forEach(input => {
input.addEventListener('input', function() {
const row = input.closest('tr'); // 해당 input이 속한 행을 찾음
calculateRowTotal(row); // 해당 행의 총합 계산
calculateAllSubtotals(); // 소계 계산
calculateGrandTotal(); // 전체 합계 계산
});
});
// 페이지 로드 시 초기 계산
window.onload = function() {
calculateAllSubtotals();
calculateGrandTotal();
};