Office Open XML Cell에 날짜/시간 값이 포함되어 있음을 나타내는 것은 무엇입니까?
Office Open XML SDK를 사용하여 .xlsx 파일을 읽고 있는데 Date/Time 값을 읽는 것이 혼란스럽습니다.스프레드시트 중 하나에 이 마크업이 있습니다(Excel 2010에서 생성됨).
<x:row r="2" spans="1:22" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<x:c r="A2" t="s">
<x:v>56</x:v>
</x:c>
<x:c r="B2" t="s">
<x:v>64</x:v>
</x:c>
.
.
.
<x:c r="J2" s="9">
<x:v>17145</x:v>
</x:c>
에는 날짜 속성 "J2"가 포함되어 있습니다.s="9"그러나 Office Open XML 사양에 따르면 9는 다음 하이퍼링크에 해당합니다.이것은 ECMA-376 제2판 제1부 - 기본 원리 및 마크업 언어 참조.pdf의 4,999페이지에서 찍은 스크린샷입니다.

은 사에포함presetCellStyles.xml 파일을 합니다.builtinId다음 하이퍼링크로 9.
<followedHyperlink builtinId="9">
규격의 모든 스타일은 숫자 스타일이 아니라 시각적 형식 스타일입니다. 참조는 어떻게 합니까?s="9"셀 형식(시각) 스타일과 숫자 스타일을 나타내는 것에서?
분명히 저는 셀의 스타일을 번호 형식과 일치시키기 위해 잘못된 곳을 찾고 있습니다.이 정보를 찾을 수 있는 올바른 장소는 어디입니까?
s 속성은 style.xml의 style xf 항목을 참조합니다.xf 스타일은 숫자 형식 마스크를 참조합니다.날짜가 포함된 셀을 식별하려면 스타일 xf -> 번호 형식 조회를 수행한 다음 해당 번호 형식 마스크가 날짜/시간 번호 형식 마스크인지(예: 백분율 또는 계정 번호 형식 마스크가 아님) 확인해야 합니다.
style.xml 파일에는 다음과 같은 요소가 있습니다.
<xf numFmtId="14" ... applyNumberFormat="1" />
<xf numFmtId="1" ... applyNumberFormat="1" />
이러한 xf 항목은 숫자 형식 마스크를 참조하는 numFmtId를 제공합니다.
스타일의 일부로 style.xml 상단 근처에 numFmts 섹션이 있어야 합니다.시트 요소
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<numFmts count="3">
<numFmt numFmtId="164" formatCode="[$-414]mmmm\ yyyy;@" />
<numFmt numFmtId="165" formatCode="0.000" />
<numFmt numFmtId="166" formatCode="#,##0.000" />
</numFmts>
번호 형식 ID는 여기에 있거나 기본 제공 형식 중 하나일 수 있습니다.164보다 작은 숫자 형식 코드(numFmtId)는 "기본 제공"입니다.
제가 가지고 있는 목록은 불완전합니다.
0 = 'General';
1 = '0';
2 = '0.00';
3 = '#,##0';
4 = '#,##0.00';
9 = '0%';
10 = '0.00%';
11 = '0.00E+00';
12 = '# ?/?';
13 = '# ??/??';
14 = 'mm-dd-yy';
15 = 'd-mmm-yy';
16 = 'd-mmm';
17 = 'mmm-yy';
18 = 'h:mm AM/PM';
19 = 'h:mm:ss AM/PM';
20 = 'h:mm';
21 = 'h:mm:ss';
22 = 'm/d/yy h:mm';
37 = '#,##0 ;(#,##0)';
38 = '#,##0 ;[Red](#,##0)';
39 = '#,##0.00;(#,##0.00)';
40 = '#,##0.00;[Red](#,##0.00)';
44 = '_("$"* #,##0.00_);_("$"* \(#,##0.00\);_("$"* "-"??_);_(@_)';
45 = 'mm:ss';
46 = '[h]:mm:ss';
47 = 'mmss.0';
48 = '##0.0E+0';
49 = '@';
27 = '[$-404]e/m/d';
30 = 'm/d/yy';
36 = '[$-404]e/m/d';
50 = '[$-404]e/m/d';
57 = '[$-404]e/m/d';
59 = 't0';
60 = 't0.00';
61 = 't#,##0';
62 = 't#,##0.00';
67 = 't0%';
68 = 't0.00%';
69 = 't# ?/?';
70 = 't# ??/??';
결측값은 주로 동아시아 변형 형식과 관련이 있습니다.
선택한 답변은 즉석에서 제공되지만 Excel은 일부 숫자 형식(numFmt) 코드를 OpenXML 사양과 다르게 정의합니다.Open XML SDK 2.5 Productivity Tool의 문서(NumberingFormat 클래스의 "Implementer Notes" 탭)에 따라 다음 작업을 수행합니다.
표준은 내장 형식 ID 14: "mm-dd-yyy", 22: "m/d/yyyh:mm", 37: "#,#0;(#,#0), 38: "#,#0;[빨간색]", 39: "#,#0.00;(#,#0.00), 40: "#,#0.00;"을 정의합니다.[빨간색]", 47: "mmss.0"; KOR fmt 55: "yyyy-mm-dd".
Excel은 기본 제공 형식 ID를 정의합니다.
14: "m/d/yyyy"
22: "m/d/yyyyh:mm"
37: "#,##0_);(#,##0)"
38: "#,##0_);[빨강]"
39: "#,##0.00_);(#,##0.00)"
40: "#,##0.00_);[빨강]"
47: "mm:ss.0"
55: "yyyy/mm/dd"
대부분은 사소한 변형이지만 #14는 바보 같은 것입니다.선두 0이 한 자리 숫자의 월과 일에 추가되지 않는 이유(예: 1/05/14 대 1/5/14)를 해결하는 데 몇 시간이 걸렸습니다.
이중 가치가 있는지 확인하기 위해 조합한 솔루션을 추가할 것이라고 생각했습니다.FromOADate진짜 데이트인지 아닌지.그 이유는 엑셀 파일에도 우편번호가 있기 때문입니다.그numberingFormat텍스트인 경우 null이 됩니다.
또는 다음을 사용할 수 있습니다.numberingFormatId그리고 목록과 대조하여 확인합니다.IdsExcel에서 날짜로 사용합니다.
이 경우 클라이언트에 대한 모든 필드의 형식을 명시적으로 결정했습니다.
/// <summary>
/// Creates the datatable and parses the file into a datatable
/// </summary>
/// <param name="fileName">the file upload's filename</param>
private void ReadAsDataTable(string fileName)
{
try
{
DataTable dt = new DataTable();
using (SpreadsheetDocument spreadSheetDocument = SpreadsheetDocument.Open(string.Format("{0}/{1}", UploadPath, fileName), false))
{
WorkbookPart workbookPart = spreadSheetDocument.WorkbookPart;
IEnumerable<Sheet> sheets = spreadSheetDocument.WorkbookPart.Workbook.GetFirstChild<Sheets>().Elements<Sheet>();
string relationshipId = sheets.First().Id.Value;
WorksheetPart worksheetPart = (WorksheetPart)spreadSheetDocument.WorkbookPart.GetPartById(relationshipId);
Worksheet workSheet = worksheetPart.Worksheet;
SheetData sheetData = workSheet.GetFirstChild<SheetData>();
IEnumerable<Row> rows = sheetData.Descendants<Row>();
var cellFormats = workbookPart.WorkbookStylesPart.Stylesheet.CellFormats;
var numberingFormats = workbookPart.WorkbookStylesPart.Stylesheet.NumberingFormats;
// columns omitted for brevity
// skip first row as this row is column header names
foreach (Row row in rows.Skip(1))
{
DataRow dataRow = dt.NewRow();
for (int i = 0; i < row.Descendants<Cell>().Count(); i++)
{
bool isDate = false;
var styleIndex = (int)row.Descendants<Cell>().ElementAt(i).StyleIndex.Value;
var cellFormat = (CellFormat)cellFormats.ElementAt(styleIndex);
if (cellFormat.NumberFormatId != null)
{
var numberFormatId = cellFormat.NumberFormatId.Value;
var numberingFormat = numberingFormats.Cast<NumberingFormat>()
.SingleOrDefault(f => f.NumberFormatId.Value == numberFormatId);
// Here's yer string! Example: $#,##0.00_);[Red]($#,##0.00)
if (numberingFormat != null && numberingFormat.FormatCode.Value.Contains("mm/dd/yy"))
{
string formatString = numberingFormat.FormatCode.Value;
isDate = true;
}
}
// replace '-' with empty string
string value = GetCellValue(spreadSheetDocument, row.Descendants<Cell>().ElementAt(i), isDate);
dataRow[i] = value.Equals("-") ? string.Empty : value;
}
dt.Rows.Add(dataRow);
}
}
this.InsertMembers(dt);
dt.Clear();
}
catch (Exception ex)
{
LogHelper.Error(typeof(MemberUploadApiController), ex.Message, ex);
}
}
/// <summary>
/// Reads the cell's value
/// </summary>
/// <param name="document">current document</param>
/// <param name="cell">the cell to read</param>
/// <returns>cell's value</returns>
private string GetCellValue(SpreadsheetDocument document, Cell cell, bool isDate)
{
string value = string.Empty;
try
{
SharedStringTablePart stringTablePart = document.WorkbookPart.SharedStringTablePart;
value = cell.CellValue.InnerXml;
if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
{
return stringTablePart.SharedStringTable.ChildElements[Int32.Parse(value)].InnerText;
}
else
{
// check if this is a date or zip.
// integers will be passed into this else statement as well.
if (isDate)
{
value = DateTime.FromOADate(double.Parse(value)).ToString();
}
return value;
}
}
catch (Exception ex)
{
LogHelper.Error(typeof(MemberUploadApiController), ex.Message, ex);
}
return value;
}
styles.xml에 numFmt 노드가 있는지 확인합니다.그것은 사용되는 날짜 형식과 관련된 "9"의 numFmtId를 보유할 것이라고 생각합니다.
ECMA에서 그것이 어디에 있는지는 모르겠지만, numFmt를 검색하면 찾을 수 있을 것입니다.
셀에 날짜/시간 값이 있는지 확실하게 판단하는 방법이 명확하지 않았습니다.시간을 들여 실험을 한 후에 기본 제공 날짜/시간 형식과 사용자 지정 날짜/시간 형식을 모두 찾을 수 있는 코드(게시물 참조)를 고안했습니다.
다른 사람들이 이 문제로 어려움을 겪을 경우를 대비해, 제가 한 일은 다음과 같습니다.
새 Excel 파일을 만들고 셀 A1에 날짜 시간 문자열을 넣습니다.
셀의 형식을 원하는 대로 변경한 다음 파일을 저장합니다.
다음 powershell 스크립트를 실행하여 .xlxs에서 스타일시트를 추출합니다.
[Reflection.Assembly]::LoadWithPartialName("DocumentFormat.OpenXml")
$xlsx = (ls C:\PATH\TO\FILE.xlsx).FullName
$package = [DocumentFormat.OpenXml.Packaging.SpreadsheetDocument]::Open($xlsx, $true)
[xml]$style = $package.WorkbookPart.WorkbookStylesPart.Stylesheet.OuterXml
Out-File -InputObject $style.OuterXml -FilePath "style.xml"
style.xml이제 주입할 수 있는 정보가 포함되어 있습니다.DocumentFormat.OpenXml.Spreadsheet.Stylesheet(string outerXml)로 이어지는.
추출된 파일을 사용하여 Excel 객체 모델 구성
var style = File.ReadAllText(@"c:\PATH\TO\EXTRACTED\Style.xml");
var stylesheetPart = WorkbookPart_REFERENCE.AddNewPart<WorkbookStylesPart>();
stylesheetPart.Stylesheet = new Stylesheet(style);
stylesheetPart.Stylesheet.Save();
@코드 스니펫에 대한 RobScott 참조 특정 셀의 스타일 인덱스에서 항상 null을 찾았습니다.
var styleIndex = (int)row.Descendants<Cell>().ElementAt(i).StyleIndex.Value;
아래에 언급된 엑셀을 읽고 행과 열 데이터를 json으로 전송해야 하는 나의 요구 사항.
탁월한 참고 문헌
| 재고 송장 번호 | 재고 송장 설정 | 이름. | 묘사 |
|---|---|---|---|
| DC3320012989 | 23-01-2021 00:00:00:00 | 항목 1 | 묘사 |
| DC3320012989 | 24-01-2021 00:00:00:00 | 항목 2 | 묘사 |
| DC3320012989 | 25-01-2021 00:00:00:00 | 항목 3 | 묘사 |
언급URL : https://stackoverflow.com/questions/4730152/what-indicates-an-office-open-xml-cell-contains-a-date-time-value
'source' 카테고리의 다른 글
| NSLog에서 부울 플래그를 인쇄하는 방법은 무엇입니까? (0) | 2023.05.20 |
|---|---|
| jQuery Event : div의 html/text 변경사항 탐지 (0) | 2023.05.20 |
| Git에서 손실된 저장소를 복구하려면 어떻게 해야 합니까? (0) | 2023.05.20 |
| Excel 파일(.xlsx)에 데이터를 쓰는 방법 (0) | 2023.05.20 |
| new를 사용하여 C++에서 2d 배열을 선언하려면 어떻게 해야 합니까? (0) | 2023.05.20 |