Exports datatable to CSV or Excel format

None.gif //  ---------------------------------------------------------
None.gif
//  Rama Krishna's Export class
None.gif
//  Copyright (C) 2004 Rama Krishna. All rights reserved.
None.gif
//  ---------------------------------------------------------
None.gif

None.gif# region Includesdot.gif
None.gif
using  System;
None.gif
using  System.Data;
None.gif
using  System.Web;
None.gif
using  System.Web.SessionState;
None.gif
using  System.IO;
None.gif
using  System.Text;
None.gif
using  System.Xml;
None.gif
using  System.Xml.Xsl;
None.gif
using  System.Threading;
None.gif
None.gif# endregion 
//  Includesdot.gif
None.gif

None.gif
namespace  DMD.Web.Module
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    # region Summary
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
/**//// <summary>
InBlock.gif    
/// Exports datatable to CSV or Excel format.
InBlock.gif    
/// This uses DataSet's XML features and XSLT for exporting.
InBlock.gif    
/// </summary>
InBlock.gif    
/// <example>
InBlock.gif    
/// C#.Net Example to be used in WebForms
InBlock.gif    
/// ------------------------------------- 
InBlock.gif    
/// using MyLib.ExportData;
InBlock.gif    
/// 
InBlock.gif    
/// private void btnExport_Click(object sender, System.EventArgs e)
InBlock.gif    
/// {
InBlock.gif    
///   try
InBlock.gif    
///   {
InBlock.gif    
///     // Declarations
InBlock.gif    
///     DataSet dsUsers =  ((DataSet) Session["dsUsers"]).Copy( );
InBlock.gif    
///     MyLib.ExportData.Export oExport = new MyLib.ExportData.Export("Web"); 
InBlock.gif    
///     string FileName = "UserList.csv";
InBlock.gif    
///     int[] ColList = {2, 3, 4, 5, 6};
InBlock.gif    
///     oExport.ExportDetails(dsUsers.Tables[0], ColList, Export.ExportFormat.CSV, FileName);
InBlock.gif    
///   }
InBlock.gif    
///   catch(Exception Ex)
InBlock.gif    
///   {
InBlock.gif    
///     lblError.Text = Ex.Message;
InBlock.gif    
///   }
InBlock.gif    
/// }    
InBlock.gif    
///  
InBlock.gif    
/// VB.Net Example to be used in WindowsForms
InBlock.gif    
/// ----------------------------------------- 
InBlock.gif    
/// Imports MyLib.ExportData
InBlock.gif    
/// 
InBlock.gif    
/// Private Sub btnExport_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
InBlock.gif    
/// 
InBlock.gif    
///      Try    
InBlock.gif    
///      
InBlock.gif    
///     'Declarations
InBlock.gif    
///     Dim dsUsers As DataSet = (CType(Session("dsUsers"), DataSet)).Copy()
InBlock.gif    
///     Dim oExport As New MyLib.ExportData.Export("Win")
InBlock.gif    
///     Dim FileName As String = "C:\\UserList.xls"
InBlock.gif    
///     Dim ColList() As Integer = New Integer() {2, 3, 4, 5, 6}            
InBlock.gif    
///     oExport.ExportDetails(dsUsers.Tables(0), ColList, Export.ExportFormat.CSV, FileName)     
InBlock.gif    
///     
InBlock.gif    
///   Catch Ex As Exception
InBlock.gif    
///     lblError.Text = Ex.Message
InBlock.gif    
///   End Try
InBlock.gif    
///   
InBlock.gif    
/// End Sub
ExpandedSubBlockEnd.gif    
/// </example>
InBlock.gif
InBlock.gif    # endregion 
// Summary
InBlock.gif

InBlock.gif    
public class Export
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{        
ExpandedSubBlockStart.gifContractedSubBlock.gif        
public enum ExportFormat : int dot.gif{CSV = 1, Excel = 2}// Export format enumeration
InBlock.gif
    
InBlock.gif        System.Web.HttpResponse response;
InBlock.gif        
private string appType;    
InBlock.gif            
InBlock.gif        
public Export()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            appType 
= "Web";
InBlock.gif            response 
= System.Web.HttpContext.Current.Response;
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public Export(string ApplicationType)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            appType 
= ApplicationType;
InBlock.gif            
if(appType != "Web" && appType != "Win"throw new Exception("Provide valid application format (Web/Win)");
InBlock.gif            
if (appType == "Web") response = System.Web.HttpContext.Current.Response;
ExpandedSubBlockEnd.gif        }

InBlock.gif        
ContractedSubBlock.gifExpandedSubBlockStart.gif        
ExportDetails OverLoad : Type#1#region ExportDetails OverLoad : Type#1
InBlock.gif        
InBlock.gif        
// Function  : ExportDetails 
InBlock.gif        
// Arguments : DetailsTable, FormatType, FileName
InBlock.gif        
// Purpose     : To get all the column headers in the datatable and 
InBlock.gif        
//               exorts in CSV / Excel format with all columns
InBlock.gif

InBlock.gif        
public void ExportDetails(DataTable DetailsTable, ExportFormat FormatType, string FileName)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{                
InBlock.gif                
if(DetailsTable.Rows.Count == 0
InBlock.gif                    
throw new Exception("There are no details to export.");                
InBlock.gif                
InBlock.gif                
// Create Dataset
InBlock.gif
                DataSet dsExport = new DataSet("Export");
InBlock.gif                DataTable dtExport 
= DetailsTable.Copy();
InBlock.gif                dtExport.TableName 
= "Values"
InBlock.gif                dsExport.Tables.Add(dtExport);    
InBlock.gif                
InBlock.gif                
// Getting Field Names
InBlock.gif
                string[] sHeaders = new string[dtExport.Columns.Count];
InBlock.gif                
string[] sFileds = new string[dtExport.Columns.Count];
InBlock.gif                
InBlock.gif                
for (int i=0; i < dtExport.Columns.Count; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    sHeaders[i] 
= dtExport.Columns[i].ColumnName;
InBlock.gif                    sFileds[i] 
= dtExport.Columns[i].ColumnName;                    
ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                
if(appType == "Web")
InBlock.gif                    Export_with_XSLT_Web(dsExport, sHeaders, sFileds, FormatType, FileName);
InBlock.gif                
else if(appType == "Win")
InBlock.gif                    Export_with_XSLT_Windows(dsExport, sHeaders, sFileds, FormatType, FileName);
ExpandedSubBlockEnd.gif            }
            
InBlock.gif            
catch(Exception Ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw Ex;
ExpandedSubBlockEnd.gif            }
            
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedSubBlockEnd.gif        
#endregion // ExportDetails OverLoad : Type#1
InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
ExportDetails OverLoad : Type#2#region ExportDetails OverLoad : Type#2
InBlock.gif
InBlock.gif        
// Function  : ExportDetails 
InBlock.gif        
// Arguments : DetailsTable, ColumnList, FormatType, FileName        
InBlock.gif        
// Purpose     : To get the specified column headers in the datatable and
InBlock.gif        
//               exorts in CSV / Excel format with specified columns
InBlock.gif

InBlock.gif        
public void ExportDetails(DataTable DetailsTable, int[] ColumnList, ExportFormat FormatType, string FileName)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if(DetailsTable.Rows.Count == 0)
InBlock.gif                    
throw new Exception("There are no details to export");
InBlock.gif                
InBlock.gif                
// Create Dataset
InBlock.gif
                DataSet dsExport = new DataSet("Export");
InBlock.gif                DataTable dtExport 
= DetailsTable.Copy();
InBlock.gif                dtExport.TableName 
= "Values"
InBlock.gif                dsExport.Tables.Add(dtExport);
InBlock.gif
InBlock.gif                
if(ColumnList.Length > dtExport.Columns.Count)
InBlock.gif                    
throw new Exception("ExportColumn List should not exceed Total Columns");
InBlock.gif                
InBlock.gif                
// Getting Field Names
InBlock.gif
                string[] sHeaders = new string[ColumnList.Length];
InBlock.gif                
string[] sFileds = new string[ColumnList.Length];
InBlock.gif                
InBlock.gif                
for (int i=0; i < ColumnList.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
if((ColumnList[i] < 0|| (ColumnList[i] >= dtExport.Columns.Count))
InBlock.gif                        
throw new Exception("ExportColumn Number should not exceed Total Columns Range");
InBlock.gif                    
InBlock.gif                    sHeaders[i] 
= dtExport.Columns[ColumnList[i]].ColumnName;
InBlock.gif                    sFileds[i] 
= dtExport.Columns[ColumnList[i]].ColumnName;                    
ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                
if(appType == "Web")
InBlock.gif                    Export_with_XSLT_Web(dsExport, sHeaders, sFileds, FormatType, FileName);
InBlock.gif                
else if(appType == "Win")
InBlock.gif                    Export_with_XSLT_Windows(dsExport, sHeaders, sFileds, FormatType, FileName);
ExpandedSubBlockEnd.gif            }
            
InBlock.gif            
catch(Exception Ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw Ex;
ExpandedSubBlockEnd.gif            }
            
ExpandedSubBlockEnd.gif        }

InBlock.gif        
ExpandedSubBlockEnd.gif        
#endregion // ExportDetails OverLoad : Type#2
InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
ExportDetails OverLoad : Type#3#region ExportDetails OverLoad : Type#3
InBlock.gif
InBlock.gif        
// Function  : ExportDetails 
InBlock.gif        
// Arguments : DetailsTable, ColumnList, Headers, FormatType, FileName    
InBlock.gif        
// Purpose     : To get the specified column headers in the datatable and    
InBlock.gif        
//               exorts in CSV / Excel format with specified columns and 
InBlock.gif        
//               with specified headers
InBlock.gif

InBlock.gif        
public void ExportDetails(DataTable DetailsTable, int[] ColumnList, string[] Headers, ExportFormat FormatType, 
InBlock.gif            
string FileName)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
if(DetailsTable.Rows.Count == 0)
InBlock.gif                    
throw new Exception("There are no details to export");
InBlock.gif                
InBlock.gif                
// Create Dataset
InBlock.gif
                DataSet dsExport = new DataSet("Export");
InBlock.gif                DataTable dtExport 
= DetailsTable.Copy();
InBlock.gif                dtExport.TableName 
= "Values"
InBlock.gif                dsExport.Tables.Add(dtExport);
InBlock.gif
InBlock.gif                
if(ColumnList.Length != Headers.Length)
InBlock.gif                    
throw new Exception("ExportColumn List and Headers List should be of same length");
InBlock.gif                
else if(ColumnList.Length > dtExport.Columns.Count || Headers.Length > dtExport.Columns.Count)
InBlock.gif                    
throw new Exception("ExportColumn List should not exceed Total Columns");
InBlock.gif                
InBlock.gif                
// Getting Field Names
InBlock.gif
                string[] sFileds = new string[ColumnList.Length];
InBlock.gif                
InBlock.gif                
for (int i=0; i < ColumnList.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    
if((ColumnList[i] < 0|| (ColumnList[i] >= dtExport.Columns.Count))
InBlock.gif                        
throw new Exception("ExportColumn Number should not exceed Total Columns Range");
InBlock.gif                    
InBlock.gif                    sFileds[i] 
= dtExport.Columns[ColumnList[i]].ColumnName;                    
ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                
if(appType == "Web")
InBlock.gif                    Export_with_XSLT_Web(dsExport, Headers, sFileds, FormatType, FileName);
InBlock.gif                
else if(appType == "Win")
InBlock.gif                    Export_with_XSLT_Windows(dsExport, Headers, sFileds, FormatType, FileName);
ExpandedSubBlockEnd.gif            }
            
InBlock.gif            
catch(Exception Ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw Ex;
ExpandedSubBlockEnd.gif            }
            
ExpandedSubBlockEnd.gif        }

InBlock.gif        
ExpandedSubBlockEnd.gif        
#endregion // ExportDetails OverLoad : Type#3
InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
Export_with_XSLT_Web#region Export_with_XSLT_Web
InBlock.gif
InBlock.gif        
// Function  : Export_with_XSLT_Web 
InBlock.gif        
// Arguments : dsExport, sHeaders, sFileds, FormatType, FileName
InBlock.gif        
// Purpose   : Exports dataset into CSV / Excel format
InBlock.gif

InBlock.gif        
private void Export_with_XSLT_Web(DataSet dsExport, string[] sHeaders, string[] sFileds, ExportFormat FormatType, string FileName)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{                
InBlock.gif                
// Appending Headers
InBlock.gif
                response.Clear();
InBlock.gif                response.Buffer
= true;
InBlock.gif                
InBlock.gif                
if(FormatType == ExportFormat.CSV)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    response.ContentType 
= "text/csv";
InBlock.gif                    response.AppendHeader(
"content-disposition""attachment; filename=" + FileName);
ExpandedSubBlockEnd.gif                }
        
InBlock.gif                
else
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    response.ContentType 
= "application/vnd.ms-excel";
InBlock.gif                    response.AppendHeader(
"content-disposition""attachment; filename=" + FileName);
ExpandedSubBlockEnd.gif                }

InBlock.gif
InBlock.gif                
// XSLT to use for transforming this dataset.                        
InBlock.gif
                MemoryStream stream = new MemoryStream( );
InBlock.gif                XmlTextWriter writer 
= new XmlTextWriter(stream, Encoding.UTF8);
InBlock.gif                
InBlock.gif                CreateStylesheet(writer, sHeaders, sFileds, FormatType);
InBlock.gif                writer.Flush( ); 
InBlock.gif                stream.Seek( 
0, SeekOrigin.Begin); 
InBlock.gif
InBlock.gif                XmlDataDocument xmlDoc 
= new XmlDataDocument(dsExport);
InBlock.gif                XslTransform xslTran 
= new XslTransform();                
InBlock.gif                xslTran.Load(
new XmlTextReader(stream), nullnull);
InBlock.gif                                
InBlock.gif                System.IO.StringWriter  sw 
= new System.IO.StringWriter();            
InBlock.gif                xslTran.Transform(xmlDoc, 
null, sw, null);
InBlock.gif                                    
InBlock.gif                
//Writeout the Content                
InBlock.gif
                response.Write(sw.ToString());                
InBlock.gif                sw.Close();    
InBlock.gif                writer.Close();
InBlock.gif                stream.Close();            
InBlock.gif                response.End();
ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch(ThreadAbortException Ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
string ErrMsg = Ex.Message;
ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch(Exception Ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw Ex;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }
        
InBlock.gif        
ExpandedSubBlockEnd.gif        
#endregion // Export_with_XSLT 
InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
Export_with_XSLT_Windows#region Export_with_XSLT_Windows 
InBlock.gif
InBlock.gif        
// Function  : Export_with_XSLT_Windows 
InBlock.gif        
// Arguments : dsExport, sHeaders, sFileds, FormatType, FileName
InBlock.gif        
// Purpose   : Exports dataset into CSV / Excel format
InBlock.gif

InBlock.gif        
private void Export_with_XSLT_Windows(DataSet dsExport, string[] sHeaders, string[] sFileds, ExportFormat FormatType, string FileName)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{                
InBlock.gif                
// XSLT to use for transforming this dataset.                        
InBlock.gif
                MemoryStream stream = new MemoryStream( );
InBlock.gif                XmlTextWriter writer 
= new XmlTextWriter(stream, Encoding.UTF8);
InBlock.gif                
InBlock.gif                CreateStylesheet(writer, sHeaders, sFileds, FormatType);
InBlock.gif                writer.Flush( ); 
InBlock.gif                stream.Seek( 
0, SeekOrigin.Begin); 
InBlock.gif
InBlock.gif                XmlDataDocument xmlDoc 
= new XmlDataDocument(dsExport);
InBlock.gif                XslTransform xslTran 
= new XslTransform();                
InBlock.gif                xslTran.Load(
new XmlTextReader(stream), nullnull);
InBlock.gif                                
InBlock.gif                System.IO.StringWriter  sw 
= new System.IO.StringWriter();            
InBlock.gif                xslTran.Transform(xmlDoc, 
null, sw, null);
InBlock.gif                                    
InBlock.gif                
//Writeout the Content                                    
InBlock.gif
                StreamWriter strwriter =  new StreamWriter(FileName);
InBlock.gif                strwriter.WriteLine(sw.ToString());
InBlock.gif                strwriter.Close();
InBlock.gif                
InBlock.gif                sw.Close();    
InBlock.gif                writer.Close();
InBlock.gif                stream.Close();    
ExpandedSubBlockEnd.gif            }
            
InBlock.gif            
catch(Exception Ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw Ex;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }
        
InBlock.gif        
ExpandedSubBlockEnd.gif        
#endregion // Export_with_XSLT 
InBlock.gif
ContractedSubBlock.gifExpandedSubBlockStart.gif        
CreateStylesheet#region CreateStylesheet 
InBlock.gif
InBlock.gif        
// Function  : WriteStylesheet 
InBlock.gif        
// Arguments : writer, sHeaders, sFileds, FormatType
InBlock.gif        
// Purpose   : Creates XSLT file to apply on dataset's XML file 
InBlock.gif

InBlock.gif        
private void CreateStylesheet(XmlTextWriter writer, string[] sHeaders, string[] sFileds, ExportFormat FormatType)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
// xsl:stylesheet
InBlock.gif
                string ns = "http://www.w3.org/1999/XSL/Transform";    
InBlock.gif                writer.Formatting 
= Formatting.Indented;
InBlock.gif                writer.WriteStartDocument( );                
InBlock.gif                writer.WriteStartElement(
"xsl","stylesheet",ns);
InBlock.gif                writer.WriteAttributeString(
"version","1.0");
InBlock.gif                writer.WriteStartElement(
"xsl:output");
InBlock.gif                writer.WriteAttributeString(
"method","text");
InBlock.gif                writer.WriteAttributeString(
"version","4.0");
InBlock.gif                writer.WriteEndElement( );
InBlock.gif                
InBlock.gif                
// xsl-template
InBlock.gif
                writer.WriteStartElement("xsl:template");
InBlock.gif                writer.WriteAttributeString(
"match","/");
InBlock.gif
InBlock.gif                
// xsl:value-of for headers
InBlock.gif
                for(int i=0; i< sHeaders.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{
InBlock.gif                    writer.WriteString(
"\"");
InBlock.gif
                    writer.WriteStartElement("xsl:value-of");
InBlock.gif                    writer.WriteAttributeString(
"select""'" + sHeaders[i] + "'");
InBlock.gif                    writer.WriteEndElement( ); 
// xsl:value-of
InBlock.gif
                    writer.WriteString("\"");
InBlock.gif
                    if (i != sFileds.Length - 1) writer.WriteString( (FormatType == ExportFormat.CSV ) ? "," : "    " );
ExpandedSubBlockEnd.gif                }

InBlock.gif                                
InBlock.gif                
// xsl:for-each
InBlock.gif
                writer.WriteStartElement("xsl:for-each");
InBlock.gif                writer.WriteAttributeString(
"select","Export/Values");
InBlock.gif                writer.WriteString(
"\r\n");                
InBlock.gif                
InBlock.gif                
// xsl:value-of for data fields
InBlock.gif
                for(int i=0; i< sFileds.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
dot.gif{                    
InBlock.gif                    writer.WriteString(
"\"");
InBlock.gif
                    writer.WriteStartElement("xsl:value-of");
InBlock.gif                    writer.WriteAttributeString(
"select", sFileds[i]);
InBlock.gif                    writer.WriteEndElement( ); 
// xsl:value-of
InBlock.gif
                    writer.WriteString("\"");
InBlock.gif
                    if (i != sFileds.Length - 1) writer.WriteString( (FormatType == ExportFormat.CSV ) ? "," : "    " );
ExpandedSubBlockEnd.gif                }

InBlock.gif                                
InBlock.gif                writer.WriteEndElement( ); 
// xsl:for-each
InBlock.gif
                writer.WriteEndElement( ); // xsl-template
InBlock.gif
                writer.WriteEndElement( ); // xsl:stylesheet
InBlock.gif
                writer.WriteEndDocument( );                    
ExpandedSubBlockEnd.gif            }

InBlock.gif            
catch(Exception Ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
dot.gif{
InBlock.gif                
throw Ex;
ExpandedSubBlockEnd.gif            }

ExpandedSubBlockEnd.gif        }

InBlock.gif        
ExpandedSubBlockEnd.gif        
#endregion // WriteStylesheet
InBlock.gif
ExpandedSubBlockEnd.gif    }

InBlock.gif
ExpandedBlockEnd.gif}

None.gif
http://www.cnblogs.com/hardrock/archive/2005/12/27/305970.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值