Java를 사용하여 프로젝트의 Gantt 차트 읽기

MS Project는 프로젝트 활동을 효율적으로 구성, 관리 및 추적하는 데 널리 사용되는 널리 사용되는 프로젝트 관리 소프트웨어입니다. 작업 생성, 리소스 추가, 리소스에 작업 할당, 진행 상황 모니터링 및 예산 관련 활동 관리를 허용합니다. Gantt 차트 보기는 프로젝트의 기본 보기입니다. 프로젝트 작업을 나열하고 서로 간의 관계를 보여줍니다. 또한 Gantt 막대를 사용하여 프로젝트 일정을 보여줍니다. 이 기사에서는 Java를 사용하여 MS 프로젝트의 Gantt 차트를 읽는 방법을 배웁니다.

이 기사에서는 다음 주제를 다룹니다.

Microsoft Project의 Gantt 차트란?

Gantt 차트는 프로젝트 일정을 보여주는 일종의 막대 차트입니다. 시간에 대한 프로젝트 작업의 그래픽 표현이며 전체 프로젝트의 조감도를 제공합니다. Microsoft Project의 Gantt 차트 보기에는 다음이 표시됩니다.

  • 프로젝트 일정
  • 예상 시간
  • 프로젝트 리소스 및 팀 구성원
  • 작업 우선 순위
  • 작업 종속성
Gantt Chart View of a Project in Microsoft Project.

Gantt Chart View of a Project in Microsoft Project.

프로젝트의 Gantt 차트를 읽는 Java API

MPP 파일에서 프로젝트의 Gantt 차트 보기를 읽기 위해 Aspose.Tasks for Java API를 사용합니다. Java 응용 프로그램에서 프로그래밍 방식으로 Microsoft Project 파일을 생성, 편집 또는 조작할 수 있습니다. API의 Project 클래스는 프로젝트를 나타냅니다. 다양한 기능을 수행하기 위해 다양한 메소드를 노출하는 메인 클래스입니다. 또한 MPP, MPT, MPXXML과 같이 지원되는 프로젝트 관리 형식 중 하나를 읽을 수 있습니다. API의 GanttChartView 클래스는 Gantt 차트 보기를 나타냅니다. 프로그래밍 방식으로 Gantt 차트를 사용할 수 있는 다양한 속성과 메서드를 제공합니다.

API의 JAR을 다운로드하거나 Maven 기반 Java 애플리케이션에서 다음 pom.xml 구성을 추가하십시오.

<repository>
    <id>AsposeJavaAPI</id>
    <name>Aspose Java API</name>
    <url>http://repository.aspose.com/repo/</url>
</repository>
<dependency>
    <groupId>com.aspose</groupId>
    <artifactId>aspose-tasks</artifactId>
    <version>22.5</version>
    <classifier>jdk18</classifier>
</dependency>

Gantt 차트 보기 읽기 및 막대 스타일 검색

API의 GanttBarStyle 클래스는 Gantt 차트 보기에서 MS Project에서 사용하는 막대 스타일을 나타냅니다. Gantt 차트 보기를 읽고 아래 단계에 따라 막대 스타일을 검색할 수 있습니다.

  1. 먼저 Project 클래스를 사용하여 프로젝트 파일을 로드합니다.
  2. 다음으로, 해당 인덱스로 ViewCollection에서 기본 보기를 가져옵니다.
  3. 그런 다음 GanttChartView 클래스 및 typecast 보기의 인스턴스를 만듭니다.
  4. 선택적으로 기본 속성을 읽고 데이터를 표시합니다.
  5. 그런 다음 getBarStyles()을 사용하여 Gantt 차트 보기의 막대 스타일 목록을 가져옵니다.
  6. 마지막으로 GanttBarStyle 클래스 개체로 막대 스타일을 반복하고 값을 표시합니다.

다음 코드 예제는 Java에서 Gantt 차트 보기의 막대 스타일을 읽는 방법을 보여줍니다.

public static void main(String[] args) throws Exception
{
    // 문서 디렉토리의 경로입니다.
    String dataDir = "C:\\Files\\Tasks\\";

    // 프로젝트 로드
    Project project = new Project(dataDir + "Project.mpp");

    // 기본 보기를 GanttChartView로 가져오기
    View view = project.getViews().toList().get(0);
    GanttChartView gcView = (GanttChartView) view;

    // 기본 정보 표시
    System.out.println("Bar Rounding: " + gcView.getBarRounding());
    System.out.println("Show Bar Splits: " + gcView.getShowBarSplits());
    System.out.println("Show Drawings: " + gcView.getShowDrawings());
    System.out.println("RollUp Gantt Bars: " + gcView.getRollUpGanttBars());
    System.out.println("Hide Rollup Bars When Summary Expanded: " + gcView.getHideRollupBarsWhenSummaryExpanded());
    System.out.println("Bar Size: " + gcView.getBarSize());
    System.out.println("Bar Styles count: " + gcView.getBarStyles().size());
    System.out.println("-----------------------------------------------");

    // 막대 스타일 표시
    for (GanttBarStyle barStyle : gcView.getBarStyles())
    {	
      System.out.println("Row: " +  barStyle.getRow());
        System.out.println("Name: " +  barStyle.getName());
        System.out.println("ShowFor: " +  barStyle.getShowForTaskUid());
        System.out.println("From:" +  getbarStylesFromToName(barStyle.getFrom()));
        System.out.println("To:" +   getbarStylesFromToName(barStyle.getTo()));
        System.out.println("Middle Shape:" +   getbarStylesMiddleShapeName(barStyle.getMiddleShape()));
        System.out.println("Middle Shape Color:" + barStyle.getMiddleShapeColor());
        System.out.println("Start Shape:" +   getbarStylesShapeName(barStyle.getStartShape()));
        System.out.println("End Shape:" +   getbarStylesShapeName(barStyle.getEndShape()));
        System.out.println("End Shape Color:" + barStyle.getEndShapeColor());
        System.out.println("-----------------------------------------------");
    }
}

// 이 함수는 필드 이름을 반환합니다.
private static String getbarStylesFromToName(int val) throws IllegalArgumentException, IllegalAccessException {
  String name = null;
  java.lang.reflect.Field[] fields = Field.class.getDeclaredFields();
  for (java.lang.reflect.Field f : fields) {
    int fVal = f.getInt(f);
      if( fVal == val)
      {
        name = f.getName();
      }
  }
  return name;
}

// 이 함수는 중간 모양 이름을 반환합니다.
private static String getbarStylesMiddleShapeName(int val) throws IllegalArgumentException, IllegalAccessException {
  String name = null;
  java.lang.reflect.Field[] fields = GanttBarMiddleShape.class.getDeclaredFields();
  for (java.lang.reflect.Field f : fields) {
    int fVal = f.getInt(f);
      if( fVal == val)
      {
        name = f.getName();
      }
  }
  return name;
}

// 이 함수는 시작 또는 끝 모양 이름을 반환합니다.
private static String getbarStylesShapeName(int val) throws IllegalArgumentException, IllegalAccessException {
  String name = null;
  java.lang.reflect.Field[] fields = GanttBarEndShape.class.getDeclaredFields();
  for (java.lang.reflect.Field f : fields) {
    int fVal = f.getInt(f);
      if( fVal == val)
      {
        name = f.getName();
      }
  }
  return name;
}
Bar Rounding: true
Show Bar Splits: true
Show Drawings: true
RollUp Gantt Bars: false
Hide Rollup Bars When Summary Expanded: false
Bar Size: 3
Bar Styles count: 40
-----------------------------------------------
Row: 1
Name: Task
ShowFor: null
From:TaskStart
To:TaskFinish
Middle Shape:RectangleBar
Middle Shape Color:java.awt.Color[r=0,g=0,b=255]
Start Shape:NoBarEndShape
End Shape:NoBarEndShape
End Shape Color:java.awt.Color[r=0,g=0,b=0]
-----------------------------------------------
...

Java에서 Gantt 차트 보기의 그리드 라인 읽기

API의 Gridlines 클래스는 Gantt 차트 보기에 나타나는 격자선을 나타냅니다. 다음 단계에 따라 그리드 선의 색상, 간격, 패턴 및 유형을 읽을 수 있습니다.

  1. 먼저 Project 클래스를 사용하여 프로젝트 파일을 로드합니다.
  2. 다음으로, 해당 인덱스로 ViewCollection에서 기본 보기를 가져옵니다.
  3. 그런 다음 GanttChartView 클래스 및 typecast 보기의 인스턴스를 만듭니다.
  4. 그런 다음 getGridlines()를 사용하여 Gantt 차트 보기의 Grid 라인 목록을 가져옵니다.
  5. 마지막으로 Gridlines 클래스 개체로 그리드 선을 반복하고 값을 표시합니다.

다음 코드 예제는 Java에서 Gantt 차트 보기의 격자선을 읽는 방법을 보여줍니다.

public static void main(String[] args) throws Exception
{
    // 문서 디렉토리의 경로입니다.
    String dataDir = "C:\\Files\\Tasks\\";

    // 프로젝트 로드
    Project project = new Project(dataDir + "Project.mpp");

    // 기본 보기를 GanttChartView로 가져오기
    GanttChartView gcView = (GanttChartView) project.getViews().toList().get(0);

    // 눈금선 정보 표시
    System.out.println("Gridlines Count: " + gcView.getGridlines().size());
    Gridlines gridlines = gcView.getGridlines().get(0);

    System.out.println("Gridlines Type: " + gridlines.getType());
    System.out.println("Gridlines Interval: " + gridlines.getInterval());
    System.out.println("Gridlines NormalColor: " + gridlines.getNormalColor());
    System.out.println("Gridlines NormalPattern: " + getLinePatternName(gridlines.getNormalPattern()));
    System.out.println("Gridlines IntervalPattern: " +gridlines.getIntervalPattern());
    System.out.println("Gridlines IntervalColor: " + gridlines.getIntervalColor());
}

// 이 함수는 라인 패턴 이름을 반환합니다.
private static String getLinePatternName(int val) throws IllegalArgumentException, IllegalAccessException {
  String name = null;
  java.lang.reflect.Field[] fields = LinePattern.class.getDeclaredFields();
  for (java.lang.reflect.Field f : fields) {
    int fVal = f.getInt(f);
      if( fVal == val)
      {
        name = f.getName();
      }
  }
  return name;
}
Gridlines Count: 14
Gridlines Type: 3
Gridlines Interval: 0
Gridlines NormalColor: java.awt.Color[r=192,g=192,b=192]
Gridlines NormalPattern: Solid
Gridlines IntervalPattern: 0
Gridlines IntervalColor: java.awt.Color[r=192,g=192,b=192]

Java에서 Gantt 차트 보기의 텍스트 스타일 추출

API의 TextStyle 클래스는 Gantt 차트 보기에서 항목에 대한 텍스트의 시각적 스타일을 나타냅니다. 아래 단계에 따라 색상, 배경색, 글꼴 및 글꼴 스타일을 읽을 수 있습니다.

  1. 먼저 Project 클래스를 사용하여 프로젝트 파일을 로드합니다.
  2. 다음으로, 해당 인덱스로 ViewCollection에서 기본 보기를 가져옵니다.
  3. 그런 다음 GanttChartView 클래스 및 typecast 보기의 인스턴스를 만듭니다.
  4. 그런 다음 getTextStyles()를 사용하여 Gantt 차트 보기의 텍스트 스타일 목록을 가져옵니다.
  5. 마지막으로 첫 번째 텍스트 스타일에 대한 TextStyle 클래스 개체를 초기화하고 값을 표시합니다.

다음 코드 예제는 Java에서 Gantt 차트 보기의 텍스트 스타일을 읽는 방법을 보여줍니다.

public static void main(String[] args) throws Exception
{
    // 문서 디렉토리의 경로입니다.
    String dataDir = "C:\\Files\\Tasks\\";

    // 프로젝트 로드
    Project project = new Project(dataDir + "Project.mpp");

    // 기본 보기를 GanttChartView로 가져오기
    GanttChartView gcView = (GanttChartView) project.getViews().toList().get(0);

    // 텍스트 스타일 정보 표시
    System.out.println("Text Styles Count: " + gcView.getTextStyles().size());
    TextStyle textStyle = gcView.getTextStyles().get(0);

    System.out.println("Background Color: " + textStyle.getBackgroundColor());
    System.out.println("Text Color: " + textStyle.getColor());
    System.out.println("Font Family: " + textStyle.getFont().getFontFamily());
    System.out.println("Font Size: " + textStyle.getFont().getSize());
    System.out.println("Font Style: " + getFontStyleName(textStyle.getFont().getStyle()));
}

// 이 함수는 글꼴 스타일 이름을 반환합니다.
private static String getFontStyleName(int val) throws IllegalArgumentException, IllegalAccessException {
  String name = null;
  java.lang.reflect.Field[] fields = FontStyles.class.getDeclaredFields();
  for (java.lang.reflect.Field f : fields) {
    int fVal = f.getInt(f);
      if( fVal == val)
      {
        name = f.getName();
      }
  }
  return name;
}
Text Styles Count: 19
Background Color: java.awt.Color[r=0,g=0,b=0]
Text Color: java.awt.Color[r=0,g=0,b=255]
Font Family: Arial
Font Size: 8.0
Font Style: Regular

Java에서 Gantt 차트 보기의 진행 라인 검색

Gantt 차트 보기에 진행 라인이 표시되어 작업이 일정보다 늦어졌는지 아니면 제대로 되었는지를 보여줍니다. 다음 단계에 따라 진행 라인의 다양한 속성을 읽을 수 있습니다.

  1. 먼저 Project 클래스를 사용하여 프로젝트 파일을 로드합니다.
  2. 다음으로, 해당 인덱스로 ViewCollection에서 기본 보기를 가져옵니다.
  3. 그런 다음 GanttChartView 클래스 및 typecast 보기의 인스턴스를 만듭니다.
  4. 그런 다음 getProgressLines()를 사용하여 Gantt 차트 보기의 진행 라인 목록을 가져옵니다.
  5. 마지막으로 진행 라인 속성 값을 표시합니다.

다음 코드 예제는 Java에서 Gantt 차트 보기의 진행 라인을 읽는 방법을 보여줍니다.

public static void main(String[] args) throws Exception
{
    // 문서 디렉토리의 경로입니다.
    String dataDir = "C:\\Files\\Tasks\\";

    // 프로젝트 로드
    Project project = new Project(dataDir + "Project.mpp");

    // 기본 보기를 GanttChartView로 가져오기
    GanttChartView gcView = (GanttChartView) project.getViews().toList().get(0);

    // 진행 라인 정보 표시
    System.out.println("ProgressLines.BeginAtDate: " + gcView.getProgressLines().getBeginAtDate().toString());
    System.out.println("ProgressLines.isBaselinePlan: " + gcView.getProgressLines().isBaselinePlan());
    System.out.println( "ProgressLines.DisplaySelected: " + gcView.getProgressLines().getDisplaySelected());
    System.out.println("ProgressLines.SelectedDates.Count: " + gcView.getProgressLines().getSelectedDates().size());

    System.out.println("ProgressLines.DisplayAtRecurringIntervals: " + gcView.getProgressLines().getDisplayAtRecurringIntervals());
    System.out.println("ProgressLines.RecurringInterval.Interval: " +  gcView.getProgressLines().getRecurringInterval().getInterval()  );
    System.out.println("ProgressLines.RecurringInterval.WeeklyDays.Count" +  gcView.getProgressLines().getRecurringInterval().getWeeklyDays().size());
    System.out.println("RecurringInterval.DayType.Friday: "  +  (int) gcView.getProgressLines().getRecurringInterval().getWeeklyDays().get(1));
    System.out.println("RecurringInterval.DayType.Saturday: "  + (int)gcView.getProgressLines().getRecurringInterval().getWeeklyDays().get(2));
    System.out.println("RecurringInterval.DayType.Sunday: " +  (int)gcView.getProgressLines().getRecurringInterval().getWeeklyDays().get(0));

    System.out.println("ProgressLines.ShowDate" + gcView.getProgressLines().getShowDate());

    System.out.println("ProgressLines.ProgressPointShape: " +  gcView.getProgressLines().getProgressPointShape());
    System.out.println("ProgressLines.ProgressPointColor: " +  gcView.getProgressLines().getProgressPointColor());
    System.out.println("ProgressLines.LineColor: " + gcView.getProgressLines().getLineColor());
    System.out.println("ProgressLines.LinePattern" +  gcView.getProgressLines().getLinePattern());

    System.out.println("ProgressLines.OtherProgressPointShape: " + gcView.getProgressLines().getOtherProgressPointShape());
    System.out.println("ProgressLines.OtherProgressPointColor: " + gcView.getProgressLines().getOtherProgressPointColor().toString());
    System.out.println("ProgressLines.OtherLineColor: " + gcView.getProgressLines().getOtherLineColor());
}

Java에서 하단 타임스케일 계층 읽기

시간 표시줄은 시간 단위, 일, 월, 달력 연도 또는 회계 연도를 표시합니다. 프로젝트 보기에는 개수, 단위, 레이블, 정렬 등과 같은 각 계층에 대한 시간 척도 값을 표시하는 3개의 시간 척도 계층이 있습니다. 아래 단계에 따라 맨 아래 시간 척도 계층을 읽을 수 있습니다.

  1. 먼저 Project 클래스를 사용하여 프로젝트 파일을 로드합니다.
  2. 다음으로, 해당 인덱스로 ViewCollection에서 기본 보기를 가져옵니다.
  3. 그런 다음 GanttChartView 클래스 및 typecast 보기의 인스턴스를 만듭니다.
  4. 그런 다음 getBottomTimescaleTier()를 사용하여 보기의 하단 타임스케일 계층 설정을 가져옵니다.
  5. 마지막으로 하단 시간 척도 계층 값을 표시합니다.

다음 코드 예제는 Java에서 Gantt 차트 보기의 맨 아래 타임스케일 계층을 읽는 방법을 보여줍니다.

public static void main(String[] args) throws Exception
{
    // 문서 디렉토리의 경로입니다.
    String dataDir = "C:\\Files\\Tasks\\";

    // 프로젝트 로드
    Project project = new Project(dataDir + "Project.mpp");

    // 기본 보기를 GanttChartView로 가져오기
    GanttChartView gcView = (GanttChartView) project.getViews().toList().get(0);

    // 하단 타임스케일 티어 정보 표시
    System.out.println("BottomTimescaleTier Count: " + gcView.getBottomTimescaleTier().getCount());
    System.out.println("BottomTimescaleTier Unit: " + getTimescaleUnitName(gcView.getBottomTimescaleTier().getUnit()));
    System.out.println("BottomTimescaleTier UsesFiscalYear: " + gcView.getBottomTimescaleTier().getUsesFiscalYear());
    System.out.println("BottomTimescaleTier Alignment: " + getAlignmentName(gcView.getBottomTimescaleTier().getAlignment()));
    System.out.println("BottomTimescaleTier ShowTicks: " + gcView.getBottomTimescaleTier().getShowTicks());
    System.out.println("BottomTimescaleTier Label: " + getDateLabelName(gcView.getBottomTimescaleTier().getLabel()));
}

// 이 함수는 타임스케일 데이터 레이블 이름을 반환합니다.
private static String getDateLabelName(int val) throws IllegalArgumentException, IllegalAccessException {
  String name = null;
  java.lang.reflect.Field[] fields = DateLabel.class.getDeclaredFields();
  for (java.lang.reflect.Field f : fields) {
    int fVal = f.getInt(f);
      if( fVal == val)
      {
        name = f.getName();
      }
  }
  return name;
}

// 이 함수는 정렬 제목을 반환합니다.
private static String getAlignmentName(int val) throws IllegalArgumentException, IllegalAccessException {
  String name = null;
  java.lang.reflect.Field[] fields = StringAlignment.class.getDeclaredFields();
  for (java.lang.reflect.Field f : fields) {
    int fVal = f.getInt(f);
      if( fVal == val)
      {
        name = f.getName();
      }
  }
  return name;
}

// 이 함수는 타임스케일 단위 이름을 반환합니다.
private static String getTimescaleUnitName(int val) throws IllegalArgumentException, IllegalAccessException {
  String name = null;
  java.lang.reflect.Field[] fields = TimescaleUnit.class.getDeclaredFields();
  for (java.lang.reflect.Field f : fields) {
    int fVal = f.getInt(f);
      if( fVal == val)
      {
        name = f.getName();
      }
  }
  return name;
}
BottomTimescaleTier Count: 2
BottomTimescaleTier Unit: Days
BottomTimescaleTier UsesFiscalYear: true
BottomTimescaleTier Alignment: Center
BottomTimescaleTier ShowTicks: true
BottomTimescaleTier Label: DayOfMonthDd

Java에서 중간 타임스케일 계층 읽기

마찬가지로 앞에서 언급한 단계에 따라 중간 시간 척도 계층을 읽을 수 있습니다. 그러나 4단계에서 getMiddleTimescaleTier()을 사용하여 보기의 중간 타임스케일 계층 설정을 가져옵니다.

다음 코드 예제는 Java에서 Gantt 차트 보기의 중간 타임스케일 계층을 읽는 방법을 보여줍니다.

public static void main(String[] args) throws Exception
{
    // 문서 디렉토리의 경로입니다.
    String dataDir = "C:\\Files\\Tasks\\";

    // 프로젝트 로드
    Project project = new Project(dataDir + "Project.mpp");

    // 기본 보기를 GanttChartView로 가져오기
    GanttChartView gcView = (GanttChartView) project.getViews().toList().get(0);

    // 중간 시간대 계층 정보 표시
    System.out.println("MiddleTimescaleTier Count: " + gcView.getMiddleTimescaleTier().getCount());
    System.out.println("TimescaleUnit Weeks: " +  getTimescaleUnitName(gcView.getMiddleTimescaleTier().getUnit()));
    System.out.println("MiddleTimescaleTier Alignment: " + getAlignmentName(gcView.getMiddleTimescaleTier().getAlignment()));
    System.out.println("MiddleTimescaleTier ShowTicks: " + gcView.getMiddleTimescaleTier().getShowTicks());
    System.out.println("MiddleTimescaleTier Label: " +  getDateLabelName(gcView.getMiddleTimescaleTier().getLabel()));
}
MiddleTimescaleTier.Count: 1
TimescaleUnit.Weeks: Months
MiddleTimescaleTier.Alignment: Center
MiddleTimescaleTier.ShowTicks: true
MiddleTimescaleTier.Label: MonthMmmmYyyy

Java에서 최상위 타임스케일 계층 검색

앞서 언급한 단계에 따라 최상위 타임스케일 계층을 읽을 수도 있습니다. 그러나 4단계에서 getTopTimescaleTier()를 사용하여 보기의 최상위 타임스케일 계층 설정을 가져옵니다.

다음 코드 예제는 Java에서 Gantt 차트 보기의 최상위 타임스케일 계층을 읽는 방법을 보여줍니다.

public static void main(String[] args) throws Exception
{
    // 문서 디렉토리의 경로입니다.
    String dataDir = "C:\\Files\\Tasks\\";

    // 프로젝트 로드
    Project project = new Project(dataDir + "Project.mpp");

    // 기본 보기를 GanttChartView로 가져오기
    GanttChartView gcView = (GanttChartView) project.getViews().toList().get(0);

    // 최상위 타임스케일 계층 정보 표시
    System.out.println("TopTimescaleTier Unit: " + getTimescaleUnitName(gcView.getTopTimescaleTier().getUnit()));
    System.out.println("TopTimescaleTier UsesFiscalYear: " + gcView.getTopTimescaleTier().getUsesFiscalYear() );
    System.out.println("TopTimescaleTier Alignment: " +  getAlignmentName(gcView.getTopTimescaleTier().getAlignment()));
    System.out.println("TopTimescaleTier ShowTicks: " + gcView.getTopTimescaleTier().getShowTicks());
    System.out.println("TopTimescaleTier Label" + getDateLabelName(gcView.getTopTimescaleTier().getLabel()));
}
TopTimescaleTier Unit: Quarters
TopTimescaleTier UsesFiscalYear: true
TopTimescaleTier Alignment: Center
TopTimescaleTier ShowTicks: true
TopTimescaleTier Label: QuarterQtrQYyyy

무료 라이선스 받기

평가 제한 없이 라이브러리를 사용해 보려면 무료 임시 라이센스를 얻으십시오.

결론

이 기사에서 우리는 방법을 배웠습니다

  • Java에서 프로그래밍 방식으로 Gantt 차트 보기를 읽습니다.
  • Gantt 차트 보기의 막대 스타일과 텍스트 스타일을 추출합니다.
  • Gantt 차트 보기의 그리드 라인 및 진행 라인을 검색합니다.
  • Java를 사용하여 Gantt 차트 보기의 시간 단위를 읽습니다.

또한 문서를 사용하여 Aspose.Tasks for Java API에 대해 자세히 알아볼 수 있습니다. 모호한 부분이 있는 경우 포럼을 통해 언제든지 문의해 주십시오.

또한보십시오