Commit 3162bb0b authored by Sergey Konovalov's avatar Sergey Konovalov

open/save csv with user defined delimiters

parent ec95648c
......@@ -333,6 +333,7 @@ namespace NExtractTools
int* m_nFormatTo;
int* m_nCsvTxtEncoding;
int* m_nCsvDelimiter;
std::wstring* m_sCsvDelimiterChar;
bool* m_bPaid;
bool* m_bFromChanges;
bool* m_bDontSaveAdditional;
......@@ -356,6 +357,7 @@ namespace NExtractTools
m_nFormatTo = NULL;
m_nCsvTxtEncoding = NULL;
m_nCsvDelimiter = NULL;
m_sCsvDelimiterChar = NULL;
m_bPaid = NULL;
m_bFromChanges = NULL;
m_bDontSaveAdditional = NULL;
......@@ -379,6 +381,7 @@ namespace NExtractTools
RELEASEOBJECT(m_nFormatTo);
RELEASEOBJECT(m_nCsvTxtEncoding);
RELEASEOBJECT(m_nCsvDelimiter);
RELEASEOBJECT(m_sCsvDelimiterChar);
RELEASEOBJECT(m_bPaid);
RELEASEOBJECT(m_bFromChanges);
RELEASEOBJECT(m_bDontSaveAdditional);
......@@ -456,6 +459,8 @@ namespace NExtractTools
m_nCsvTxtEncoding = new int(XmlUtils::GetInteger(sValue));
else if(_T("m_nCsvDelimiter") == sName)
m_nCsvDelimiter = new int(XmlUtils::GetInteger(sValue));
else if(_T("m_nCsvDelimiterChar") == sName)
m_sCsvDelimiterChar = new std::wstring(sValue);
else if(_T("m_bPaid") == sName)
m_bPaid = new bool(XmlUtils::GetBoolean2(sValue));
else if(_T("m_bFromChanges") == sName)
......@@ -475,6 +480,10 @@ namespace NExtractTools
else if(_T("m_sPassword") == sName)
m_sPassword = new std::wstring(sValue);
}
else if(_T("m_nCsvDelimiterChar") == sName)
{
m_sCsvDelimiterChar = new std::wstring(L"");
}
}
}
}
......@@ -492,8 +501,8 @@ namespace NExtractTools
std::wstring getXmlOptions()
{
std::wstring sRes;
int nCsvEncoding = 65001; //utf8
std::string cDelimiter = ",";
int nCsvEncoding = 46;//65001 utf8
std::wstring cDelimiter = L"";
if(NULL != m_nCsvTxtEncoding)
nCsvEncoding = *m_nCsvTxtEncoding;
......@@ -501,13 +510,17 @@ namespace NExtractTools
{
switch (*m_nCsvDelimiter)
{
case TCSVD_TAB: cDelimiter = "\t"; break;
case TCSVD_SEMICOLON: cDelimiter = ";"; break;
case TCSVD_COLON: cDelimiter = ":"; break;
case TCSVD_COMMA: cDelimiter = ","; break;
case TCSVD_SPACE: cDelimiter = " "; break;
case TCSVD_TAB: cDelimiter = L"\t"; break;
case TCSVD_SEMICOLON: cDelimiter = L";"; break;
case TCSVD_COLON: cDelimiter = L":"; break;
case TCSVD_COMMA: cDelimiter = L","; break;
case TCSVD_SPACE: cDelimiter = L" "; break;
}
}
if(NULL != m_sCsvDelimiterChar)
{
cDelimiter = *m_sCsvDelimiterChar;
}
int nFileType = 1;
if(NULL != m_nFormatFrom && AVS_OFFICESTUDIO_FILE_SPREADSHEET_CSV == *m_nFormatFrom)
nFileType = 2;
......@@ -522,7 +535,7 @@ namespace NExtractTools
}
sRes = L"<xmlOptions><fileOptions fileType='" + std::to_wstring(nFileType);
sRes += L"' codePage='" + std::to_wstring(nCsvEncoding);
sRes += L"' delimiter='" + std::wstring(cDelimiter.begin(), cDelimiter.end()) + L"' " + sSaveType;
sRes += L"' delimiter='" + XmlUtils::EncodeXmlString(cDelimiter) + L"' " + sSaveType;
sRes += L"/><TXTOptions><Encoding>" + std::to_wstring(nCsvEncoding) + L"</Encoding></TXTOptions></xmlOptions>";
return sRes;
......@@ -602,7 +615,7 @@ namespace NExtractTools
eRes = TCD_ERROR;
}
}
else if(AVS_OFFICESTUDIO_FILE_SPREADSHEET_CSV == nFormatFrom && (NULL == m_nCsvTxtEncoding || NULL == m_nCsvDelimiter))
else if(AVS_OFFICESTUDIO_FILE_SPREADSHEET_CSV == nFormatFrom && (NULL == m_nCsvTxtEncoding || (NULL == m_nCsvDelimiter && NULL == m_sCsvDelimiterChar)))
{
if(!getDontSaveAdditional())
{
......
......@@ -40,10 +40,6 @@
#endif
#include "../../DesktopEditor/common/File.h"
#ifndef CP_UTF8
#define CP_UTF8 65001
#endif
namespace SerializeCommon
{
std::wstring DownloadImage(const std::wstring& strFile)
......@@ -99,11 +95,11 @@ namespace SerializeCommon
return sSourcePath.substr(0, nIndex + 1) + sTargetExt;
return sSourcePath;
}
void ReadFileType(const std::wstring& sXMLOptions, BYTE& result, UINT& nCodePage, WCHAR& wcDelimiter, BYTE& cSaveFileType)
void ReadFileType(const std::wstring& sXMLOptions, BYTE& result, UINT& nCodePage, std::wstring& sDelimiter, BYTE& cSaveFileType)
{
result = BinXlsxRW::c_oFileTypes::XLSX;
nCodePage = CP_UTF8;
wcDelimiter = _T(',');
nCodePage = 46;//todo 46 временно CP_UTF8
sDelimiter = _T("");
cSaveFileType = BinXlsxRW::c_oFileTypes::XLSX;
nullable<SimpleTypes::CUnsignedDecimalNumber<>> fileType;
......@@ -142,9 +138,7 @@ namespace SerializeCommon
cSaveFileType = (BYTE)saveFileType->GetValue();
if (delimiter.IsInit())
{
const std::wstring& sDelimiter = delimiter.get();
if (0 < sDelimiter.length())
wcDelimiter = sDelimiter[0];
sDelimiter = delimiter.get();
}
break;
}
......
......@@ -72,7 +72,7 @@ namespace SerializeCommon
aReplies.clear();
}
};
void ReadFileType(const std::wstring& sXMLOptions, BYTE& result, UINT& nCodePage, WCHAR& wcDelimiter, BYTE& saveFileType);
void ReadFileType(const std::wstring& sXMLOptions, BYTE& result, UINT& nCodePage, std::wstring& wcDelimiter, BYTE& saveFileType);
}
#endif //SERIALIZER_COMMON
......@@ -3926,16 +3926,16 @@ namespace BinXlsxRW
// File Type
BYTE fileType;
UINT nCodePage;
WCHAR wcDelimiter;
std::wstring sDelimiter;
BYTE saveFileType;
SerializeCommon::ReadFileType(sXMLOptions, fileType, nCodePage, wcDelimiter, saveFileType);
SerializeCommon::ReadFileType(sXMLOptions, fileType, nCodePage, sDelimiter, saveFileType);
OOX::Spreadsheet::CXlsx *pXlsx = NULL;
switch(fileType)
{
case BinXlsxRW::c_oFileTypes::CSV:
pXlsx = new OOX::Spreadsheet::CXlsx();
CSVReader::ReadFromCsvToXlsx(sInputDir, *pXlsx, nCodePage, wcDelimiter);
CSVReader::ReadFromCsvToXlsx(sInputDir, *pXlsx, nCodePage, sDelimiter);
break;
case BinXlsxRW::c_oFileTypes::XLSX:
default:
......@@ -3946,8 +3946,8 @@ namespace BinXlsxRW
if (BinXlsxRW::c_oFileTypes::JSON == saveFileType)
{
//todo 46 временно CP_UTF8
CSVWriter::WriteFromXlsxToCsv(sFileDst, *pXlsx, 46, _T(','), true);
//todo 46 временно CP_UTF8
CSVWriter::WriteFromXlsxToCsv(sFileDst, *pXlsx, 46, std::wstring(L","), true);
}
else
{
......
......@@ -81,7 +81,7 @@ namespace CSVReader
pCell->setRowCol(nRow, nCol);
oRow.m_arrItems.push_back(pCell);
}
void ReadFromCsvToXlsx(const std::wstring &sFileName, OOX::Spreadsheet::CXlsx &oXlsx, UINT nCodePage, const WCHAR wcDelimiter)
void ReadFromCsvToXlsx(const std::wstring &sFileName, OOX::Spreadsheet::CXlsx &oXlsx, UINT nCodePage, const std::wstring& sDelimiter)
{
// Создадим Workbook
oXlsx.CreateWorkbook();
......@@ -169,6 +169,20 @@ namespace CSVReader
INT nSize = sFileDataW.length();
const WCHAR *pTemp =sFileDataW.c_str();
WCHAR wcDelimiterLeading = L'\0';
WCHAR wcDelimiterTrailing = L'\0';
int nDelimiterSize = 0;
if (sDelimiter.length() > 0)
{
wcDelimiterLeading = sDelimiter[0];
nDelimiterSize = 1;
if (2 == sizeof(wchar_t) && 0xD800 <= wcDelimiterLeading && wcDelimiterLeading <= 0xDBFF && sDelimiter.length() > 1)
{
wcDelimiterTrailing = sDelimiter[1];
nDelimiterSize = 2;
}
}
const WCHAR wcNewLineN = _T('\n');
const WCHAR wcNewLineR = _T('\r');
const WCHAR wcQuote = _T('"');
......@@ -188,7 +202,7 @@ namespace CSVReader
for (INT nIndex = 0; nIndex < nSize; ++nIndex)
{
wcCurrent = pTemp[nIndex];
if (wcDelimiter == wcCurrent)
if (wcDelimiterLeading == wcCurrent && (L'\0' == wcDelimiterTrailing || (nIndex + 1 < nSize && wcDelimiterTrailing == pTemp[nIndex + 1])))
{
if (bInQuote)
continue;
......@@ -197,7 +211,7 @@ namespace CSVReader
AddCell(sCellText, nStartCell, oDeleteChars, *pRow, nIndexRow, nIndexCol++, bIsWrap);
bIsWrap = false;
nStartCell = nIndex + 1;
nStartCell = nIndex + nDelimiterSize;
if (nStartCell == nSize)
{
pWorksheet->m_oSheetData->m_arrItems.push_back(pRow);
......
......@@ -40,7 +40,7 @@
namespace CSVReader
{
void AddCell(std::wstring &sText, INT nStartCell, std::stack<INT> &oDeleteChars, OOX::Spreadsheet::CRow &oRow, INT nRow, INT nCol, bool bIsWrap);
void ReadFromCsvToXlsx(const std::wstring &sFileName, OOX::Spreadsheet::CXlsx &oXlsx, UINT nCodePage, const WCHAR wcDelimiter);
void ReadFromCsvToXlsx(const std::wstring &sFileName, OOX::Spreadsheet::CXlsx &oXlsx, UINT nCodePage, const std::wstring& wcDelimiter);
}
#endif //CSV_READER
......@@ -3916,10 +3916,10 @@ namespace BinXlsxRW {
std::wstring sDstPathCSV = sDstPath;
BYTE fileType;
UINT nCodePage;
WCHAR wcDelimiter;
std::wstring sDelimiter;
BYTE saveFileType;
SerializeCommon::ReadFileType(sXMLOptions, fileType, nCodePage, wcDelimiter, saveFileType);
SerializeCommon::ReadFileType(sXMLOptions, fileType, nCodePage, sDelimiter, saveFileType);
// Делаем для CSV перебивку пути, иначе создается папка с одинаковым имеем (для rels) и файл не создается.
if (BinXlsxRW::c_oFileTypes::CSV == fileType)
......@@ -3943,7 +3943,7 @@ namespace BinXlsxRW {
switch(fileType)
{
case BinXlsxRW::c_oFileTypes::CSV:
CSVWriter::WriteFromXlsxToCsv(sDstPathCSV, oXlsx, nCodePage, wcDelimiter, false);
CSVWriter::WriteFromXlsxToCsv(sDstPathCSV, oXlsx, nCodePage, sDelimiter, false);
break;
case BinXlsxRW::c_oFileTypes::XLSX:
default:
......
......@@ -64,7 +64,7 @@ namespace CSVWriter
}
}
}
void WriteFile(NSFile::CFileBinary *pFile, WCHAR **pWriteBuffer, INT &nCurrentIndex, std::wstring &sWriteString, UINT &nCodePage, bool bIsEnd)
void WriteFile(NSFile::CFileBinary *pFile, WCHAR **pWriteBuffer, INT &nCurrentIndex, const std::wstring &sWriteString, UINT &nCodePage, bool bIsEnd)
{
if (NULL == pFile || NULL == pWriteBuffer)
return;
......@@ -84,7 +84,7 @@ namespace CSVWriter
if (nCountChars + nCurrentIndex > c_nSize || bIsEnd)
{
// Буффер заполнился, пишем
if (nCodePage == CP_UTF16)
if (nCodePage == 48 && 2 == sizeof(wchar_t))//todo 48 временно CP_UTF16
{
pFile->WriteFile((BYTE*)*pWriteBuffer, sizeof (WCHAR) * nCurrentIndex);
}
......@@ -106,23 +106,23 @@ namespace CSVWriter
nCurrentIndex += nCountChars;
}
}
void WriteFromXlsxToCsv(const std::wstring &sFileDst, OOX::Spreadsheet::CXlsx &oXlsx, UINT nCodePage, const WCHAR wcDelimiter, bool bJSON)
void WriteFromXlsxToCsv(const std::wstring &sFileDst, OOX::Spreadsheet::CXlsx &oXlsx, UINT nCodePage, const std::wstring& sDelimiter, bool bJSON)
{
NSFile::CFileBinary oFile;
oFile.CreateFileW(sFileDst);
// Нужно записать шапку
if (CP_UTF8 == nCodePage)
if (46 == nCodePage)//todo 46 временно CP_UTF8
{
BYTE arUTF8[3] = {0xEF, 0xBB, 0xBF};
oFile.WriteFile(arUTF8, 3);
}
else if (CP_UTF16 == nCodePage)
else if (48 == nCodePage)//todo 48 временно CP_UTF16
{
BYTE arUTF16[2] = {0xFF, 0xFE};
oFile.WriteFile(arUTF16, 2);
}
else if (CP_unicodeFFFE == nCodePage)
else if (49 == nCodePage)//todo 49 временно CP_unicodeFFFE
{
BYTE arBigEndian[2] = {0xFE, 0xFF};
oFile.WriteFile(arBigEndian, 2);
......@@ -169,9 +169,8 @@ namespace CSVWriter
if (NULL != pWorksheet && pWorksheet->m_oSheetData.IsInit())
{
OOX::Spreadsheet::CSharedStrings *pSharedStrings = oXlsx.GetSharedStrings();
std::wstring sDelimiter = _T(""); sDelimiter += wcDelimiter;
std::wstring sEscape = _T("\"\n");
sEscape += wcDelimiter;
sEscape += sDelimiter;
std::wstring sEndJson = std::wstring(_T("]"));
std::wstring sQuote = _T("\"");
std::wstring sDoubleQuote = _T("\"\"");
......
......@@ -32,20 +32,13 @@
#ifndef CSV_WRITER
#define CSV_WRITER
#define CP_UTF16 1200
#define CP_unicodeFFFE 1201
#ifndef CP_UTF8
#define CP_UTF8 65001
#endif
#include "../../DesktopEditor/common/File.h"
#include "../../Common/DocxFormat/Source/XlsxFormat/Xlsx.h"
namespace CSVWriter
{
void WriteFile(NSFile::CFileBinary *pFile, WCHAR **pWriteBuffer, INT &nCurrentIndex, std::wstring &sWriteString, UINT &nCodePage, bool bIsEnd = false);
void WriteFromXlsxToCsv(const std::wstring &sFileDst, OOX::Spreadsheet::CXlsx &oXlsx, UINT nCodePage, const WCHAR wcDelimiter, bool bJSON);
void WriteFile(NSFile::CFileBinary *pFile, WCHAR **pWriteBuffer, INT &nCurrentIndex, const std::wstring &sWriteString, UINT &nCodePage, bool bIsEnd = false);
void WriteFromXlsxToCsv(const std::wstring &sFileDst, OOX::Spreadsheet::CXlsx &oXlsx, UINT nCodePage, const std::wstring& wcDelimiter, bool bJSON);
}
#endif //CSV_WRITER
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment